瀏覽器從去年年底開始,已經開始支援瀏覽器的原生平滑滾動定位,CSS scroll-behavior
屬性和JS scrollIntoView()
方法都可以。
一、CSS scroll-behavior與平滑滾動
scroll-behavior:smooth
寫在滾動容器元素上,可以讓容器(非滑鼠手勢觸發)的滾動變得平滑。
我們先看一個實際的案例。
8年前“無JavaScript純CSS實現選項卡輪轉切換效果”這篇文章介紹了一種利用錨點定位純CSS實現選項卡切換的技術(本質上是觸發滾動條滾動)。
可以狠狠地點選這裡:無JavaScript實現的切換效果demo
實現後的效果參見下GIF截圖:
基本功能可以滿足,但有兩個問題,一是由於改變location的hash實現的定位,會觸發瀏覽器原生滾動行為,體驗不好;二是選項卡內容的切換“邦邦邦”過於生硬。
於是,後來,我發明了一種基於控制元件元素focus觸發滾動重定位的特性實現的純CSS選項卡切換效果,在《CSS世界》這本書overflow章節有提到,您可以狠狠的點選這裡:focus錨點定位和overflow的選項卡切換demo
也是純CSS實現,沒有任何JavaScript程式碼,相比直接利用<a>
元素的href
錨點跳轉方法,此方法不會觸發瀏覽器外部窗體的滾動,體驗更上一層樓,但是還有一個問題,那就是選項卡內容切換的時候,還是“邦邦邦”這種乾巴巴的效果,並沒有滑來滑去那種溼溼的效果。
不要擔心,現在有了CSS scroll-behavior,則平滑滾動的問題也可以解決了。您可以狠狠地點選這裡:CSS scroll-behavior選項卡平滑滾動demo
相比之前乾巴巴的實現,就多了這麼一句CSS——scroll-behavior:smooth
:
.box {
scroll-behavior: smooth;
overflow: hidden;
}複製程式碼
結果一股如沐春風的互動效果撲面而來,參見下面視訊截圖效果(掘金文章不支援嵌入視訊,可去原文檢視),或者腦補下面的靜態圖:
更簡單更實際的用途
其實scroll-behavior
的使用沒有那麼多花頭,你就記住這麼一句話——
凡是需要滾動的地方都加一句scroll-behavior:smooth就好了!
你別管他用不用得到,也不用管瀏覽器相容性如何,你都加上。這就像一個不要錢的免費抽獎,沒有中獎,沒關係,又沒什麼損失,中獎了自然好,錦上添花!scroll-behavior:smooth
就是這種尿性。
舉個例子,在PC瀏覽器中,網頁預設滾動是在<html>
標籤上的,移動端大多數在<body>
標籤上,於是,我加上這麼一句:
html, body { scroll-behavior:smooth; }複製程式碼
此時,點選如下程式碼所示的“返回頂部”連結,就會平滑滾動到頂部。
<a href="#">返回頂部</a>複製程式碼
從這一點來看,業界瀏覽器的CSS reset都可以加上這麼一條規則:
html, body { scroll-behavior:smooth; }複製程式碼
二、JS scrollIntoView與平滑滾動
DOM元素的scrollIntoView()
方法是一個IE6瀏覽器也支援的原生JS API,可以讓元素進入視區,通過觸發滾動容器的定位實現。
隨著Chrome和Firefox瀏覽器開始支援CSS scroll-behavior
屬性,順便對,scrollIntoView()
方法進行了升級,使支援更多引數,其中一個引數就是可以使滾動平滑。
語法如下:
target.scrollIntoView({
behavior: "smooth"
});複製程式碼
我們隨便開啟一個有連結的頁面,把首個連結滾動到螢幕外,然後控制檯輸入類似下面程式碼,我們就可以看到頁面平滑滾動定位了:
document.links[0].scrollIntoView({
behavior: "smooth"
});複製程式碼
如下視訊截圖:
其它:
scrollIntoView()
升級後的方法,除了支援'behavior'
,還有'block'
和'inline'
等引數,有興趣可以參閱MDN相關文件。- 如果我們的網頁已經通過CSS設定了
scroll-behavior:smooth
宣告,則我們直接執行target.scrollIntoView()
方法就會有平滑滾動,無需再額外設定behavior
引數。例如,如果你是在鑫空間原站瀏覽的此文章,開啟控制檯,執行下面程式碼,就可以看到平滑滾動效果了:document.forms[0].scrollIntoView();複製程式碼
三、JS平滑滾動向下相容處理
JS實現平滑滾動並不難,jQuery中animate()
方法:
scrollContainer.animate({
scrollTop: 0
});複製程式碼
或者使用requestAnimationFrame API這類原生JS也能實現。例如下面這個我速寫的個方法:
/**
@description 頁面垂直平滑滾動到指定滾動高度
@author zhangxinxu(.com)
*/
var scrollSmoothTo = function (position) {
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function(callback, element) {
return setTimeout(callback, 17);
};
}
// 當前滾動高度
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
// 滾動step方法
var step = function () {
// 距離目標滾動距離
var distance = position - scrollTop;
// 目標滾動位置
scrollTop = scrollTop + distance / 5;
if (Math.abs(distance) < 1) {
window.scrollTo(0, position);
} else {
window.scrollTo(0, scrollTop);
requestAnimationFrame(step);
}
};
step();
};複製程式碼
使用的是自己私藏緩動動畫JS小演算法,滾動先快後慢。
使用如下,例如,我們希望網頁平滑滾動到頂部,直接:
scrollSmoothTo(0);複製程式碼
就可以了。
難的是如何支援平滑滾動的瀏覽器原生處理,不支援的瀏覽器還是使用老的JS方法處理。例如IE瀏覽器和Safari目前尚未支援原生平滑滾動。
需要分別處理,我的JS判斷處理如下:
if (typeof window.getComputedStyle(document.body).scrollBehavior == 'undefined') {
// 傳統的JS平滑滾動處理程式碼...
}複製程式碼
這樣就可以無縫對接了。
(本文完)