CSS scroll-behavior和JS scrollIntoView讓頁面滾動平滑
byzhangxinxu from ofollow,noindex" target="_blank">https://www.zhangxinxu.com/wordpress/?p=8073
本文可全文轉載,個人網站無需授權,只要保留原作者、出處以及文中連結即可,任何網站均可摘要聚合,商用請聯絡授權。
一、引言開始言開頭言
1. 這些年自己步子慢了
這些年自己在無障礙訪問,SVG和Canvas這些偏小眾的領域花了大量的學習精力,以至於很多前端新特性,新技術沒能及時關注和了解,有CSS3領域的新屬性,有JS領域的新API,包括全新的ES6/ES7語法等,相比以前的學習,步子確實慢了。比方說,本文要介紹的平滑滾動,無論是CSS還是JS,現代瀏覽器都提供了原生的屬性或方法支援,而且差不多已經有一年時間,而我最近才知道,和數年前實時關注新技術的自己形成了明顯的對比。
不過隨著SVG和Canvas的基礎越來越牢固,細節越來越深入,我的學習重心已經開始往廣度方向轉移,慢慢拾起那些遺落的麥穗。
2. 從乾巴巴到又溼又滑
假設頁面中有下面這一段HTML:
<a href="#" rel="internal">返回頂部</a>
幫我們點選“返回頂部”這個文字連結的時候,頁面就會“唰”地一聲瞬間定位到瀏覽器頂部,速度之快,升勢之猛,以至於你沒有任何反應,就像暴風雨般的愛情,讓你猝不及防,腦中不斷回想:“我在哪裡?我是誰?我剛剛做了什麼?”
所有這些反應的產生,歸根結底在於我們這個滾動效果實在是太乾巴巴了,機械生硬沒有靈性不解風情。
人是有情感的動物,既然我們做的網頁是給人用的,那自然充滿情感,不要那麼幹巴巴,讓滾動效果又溼又滑,使用者體驗就會好。
光滑如雪的肌膚,飽滿溼潤的紅脣,是不是總能讓人心動不已?如果我們的互動效果也能做得如此,也同樣也能讓使用者心動。
瀏覽器似乎也意識到這一點,從去年年底開始,已經開始支援瀏覽器的原生平滑滾動定位,CSS scroll-behavior
屬性和JS scrollIntoView()
方法都可以。
OK,下面開始進入正題。
二、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; }
結果一股如沐春風的互動效果撲面而來,參見下面視訊截圖效果 (若無效果,訪問原文地址) :
一行CSS就可以錦上添花。
更簡單更實際的用途
其實 scroll-behavior
的使用沒有那麼多花頭,你就記住這麼一句話——
凡是需要滾動的地方都加一句scroll-behavior:smooth就好了!
你別管他用不用得到,也不用管瀏覽器相容性如何,你都加上。這就像一個不要錢的免費抽獎,沒有中獎,沒關係,又沒什麼損失,中獎了自然好,錦上添花! scroll-behavior:smooth
就是這種尿性。
舉個例子,在PC瀏覽器中,網頁預設滾動是在 <html>
標籤上的,移動端大多數在 <body>
標籤上,於是,我加上這麼一句:
html, body { scroll-behavior:smooth; }
此時,點選下面這個“返回頂部”連結,就會平滑滾動到頂部(真·實時效果,可以點選嘗試)。
HTML程式碼如下:
<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方法處理。
我是這麼處理的JS如下判斷:
if (typeof window.getComputedStyle(document.body).scrollBehavior == 'undefined') { // 傳統的JS平滑滾動處理程式碼... }
這樣就可以無縫對接了。
五、結語結尾語結束語
沒有個人特質的文章就像沒有靈魂的機器一樣。懷念張含韻的照片,家裡領導不放心,怕侵犯版權找上門,都給下掉了,現在的那些美女照片,就像白開水一樣,索然無味……
我琢磨著要換個角色或者標籤,例如……一匹馬!
本文為原創文章,會經常更新知識點以及修正一些錯誤,因此轉載請保留原出處,方便溯源,避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗。
本文地址: https://www.zhangxinxu.com/wordpress/?p=8073
(本篇完)