原文連接:Practical CSS Scroll Snapping,by Max Kohlercss
CSS 滾動捕捉容許用戶完成滾動以後將視口鎖定到某個元素的位置。很是適合用來創建下面這樣的應用:html
實現滾動捕捉主要依靠兩個屬性:容器元素的 scroll-snap-type
屬性,以及子元素的 scroll-snap-align
屬性。最基本的使用方式以下:git
<div class="container">
<section class="child"></section>
<section class="child"></section>
<section class="child"></section>
<p>...</p>
</div>
複製代碼
.container {
scroll-snap-type: y mandatory;
}
.child {
scroll-snap-align: start;
}
複製代碼
初版中定義的屬性與此不一樣,是經過 repeat
關鍵字實現的。github
.container {
/* OLD */
scroll-snap-points-y: repeat(300px);
}
複製代碼
這種定義捕捉的方式很侷限,只在間距均勻的捕捉點(evenly-spaced snap points)場景下有效,若是個別子元素尺寸與其餘的不同,就會有問題。npm
在撰寫本文時,Firefox、Internet Explorer 和 Edge 都支持較早版本的規範,而 Chrome(69+)和 Safari 支持較新的基於元素(element-based)的方法。瀏覽器
你能夠同時使用這兩種方法(若是佈局容許),以便支持這兩類瀏覽器:app
.container {
scroll-snap-type: mandatory;
scroll-snap-points-y: repeat(300px);
scroll-snap-type: y mandatory;
}
.child {
scroll-snap-align: start;
}
複製代碼
但我認爲使用基於元素的語法纔是更靈活的選擇,你能夠一個下載 polyfill 來支持尚不支持它的瀏覽器。本文中後續的例子我也都是使用最新的語法寫的。ide
注意:工具
不幸的是,polyfill 並無附帶瀏覽器包,若是不使用構建工具的話,使用起來會有點麻煩。我發現一個最簡單的方法是連接到 bundle.run 上的腳本,並在加載 DOM 後使用
cssScrollSnapPolyfill()
進行 polyfill 初始化。還須要指出的是,此 polyfill 僅支持基於元素的語法,而不支持repeat
方法。佈局
滾動捕捉須要同時設置父元素(容器)屬性和子元素屬性。這與 Flex 佈局和網格佈局裏概念類型。
下面分別介紹。
mandatory
值表示,在用戶中止滾動時,瀏覽器必須 滾動到一個捕捉點;proximity
屬性就沒有嚴格——除非當前滾動的位置合適,不然 不會強制瀏覽器 滾動到捕捉點。以個人經驗,當滾動中止在距離某個捕捉點幾百像素內時,捕捉纔會發生。
我在工做中發現,mandatory
能提供更一致的用戶體驗。可是,規範中也指出,在遇到內容元素比滾動容器還高的狀況,使用這個值就有點危險。
若是這裏的容器元素設置了 scroll-snap-type: mandatory
,它老是會吸附到元素的頂部或下面元素的頂部,使得這個超高元素的中間部份內容是難完整查看。
默認狀況下,內容元素會吸附到容器的最邊緣。咱們能夠經過設置容器的 scroll-padding
屬性來作修改。它的語法與 padding
屬性同樣。
若是佈局中出現有可能妨礙內容元素展現的物件(好比,固定標題),使用它就比較有用。
如今再來看看,可在子元素上應用的屬性。
經過這個屬性,能夠指定元素的哪一部分吸附到容器上。可能的取值有三個:start
、center
和 end
。
這些值的含義是相對於滾動方向。若是是垂直滾動,start
指的是元素的頂部邊緣。若是你水平滾動,它指的是左邊緣。center
和 end
屬性值與此同理。屬性還支持兩個值的語法,分別指定水平和垂直方向上的捕捉對齊方向。
譯註:以
scroll-snap-align: start end;
爲例,此處第一個值表示垂直滾動時的對齊點,第二個值則表示水平滾動。更多內容,能夠參考 MDN 文檔。
默認狀況下,滾動捕捉只會在用戶中止滾動時發生,這表示若是滾動過猛,中間可能會跳過幾個捕捉點,而後纔會中止。能夠經過給子元素設置 scroll-snap-stop: always
來改變這一行爲。這會將強制滾動容器在用戶繼續滾動以前停留在在就近的一個元素上。
在寫這篇文章的時候,尚未瀏覽器原生支持 scroll-snap-stop
屬性,儘管 Chrome 有一個 tracking bug 在。
讓咱們看一些使用滾動捕捉的例子。
實現垂直吸附滾動只需用到幾行 CSS。首先,咱們告訴容器沿其垂直軸捕捉:
.container {
scroll-snap-type: y mandatory;
}
複製代碼
而後,定義吸附點(snap points)。這裏,咱們指定列表元素的頂部是吸附點:
.child {
scroll-snap-align: start;
}
複製代碼
demo:
爲了實現水平滑塊,咱們告訴容器沿其 x 軸對齊。咱們還使用 scroll-padding
確保子元素在容器中心處對齊。
.container {
scroll-snap-type: x mandatory;
scroll-padding: 50%;
}
複製代碼
而後,咱們告訴容器要吸附到哪一個點。爲了將圖庫(gallery)居中,咱們將每一個元素的中心點定爲吸附點。
.child {
scroll-snap-align: center;
}
複製代碼
demo:
咱們能夠直接在 HTML 元素上設置捕捉點:
html { /* body won't work ¯\_(ツ)_/¯ */
scroll-snap-type: y mandatory;
}
複製代碼
而後,使每一個部分的大小與視口同樣,並將頂部邊緣定義爲捕捉點:
section {
height: 100vh;
width: 100vw;
scroll-snap-align: start;
}
複製代碼
效果(demo):
******這與垂直版本具備相相似,不夠捕捉點位於 X 軸上。
body {
scroll-snap-type: x mandatory;
}
section {
height: 100vh;
width: 100vw;
scroll-snap-align: start;
}
複製代碼
效果(demo):
滾動捕捉能夠同時在兩個方向上進行。
.container {
scroll-snap-type: both mandatory;
}
複製代碼
而後,咱們將每一個圖塊的左上角定義爲捕捉點:
.tile {
scroll-snap-align: start;
}
複製代碼
效果(demo):
基於 CSS 的滾動捕捉的偉大之處在於,你無需直接控制滾動位置。取而代之的是,只需向瀏覽器提供一個位置列表,系統會自動以適合當前平臺的首選項方式作捕捉處理。這表示咱們縮寫的滾動捕獲效果感受很匹配系統風格(使用了使用相同的動畫效果)。
對我來講,這是 CSS 滾動捕捉優於提供相似功能的 JavaScript 庫的主要優點。
根據個人經驗,這在移動設備上效果還不錯。也許是由於滾動捕捉已是移動平臺上本機 UI 的一部分(iOS 和Android 設備上主屏的 App 圖表,本質上就是帶有捕捉點的水平滑塊)。Android 的 Chrome 上的交互特別好,由於它感受像是天然的滾動效果,但視口老是碰巧恰好的地方中止滾動:
在這背後確定有一些夢幻的數學公式使之成爲現實。感謝 CSS 滾動捕捉,爲咱們免費提供了這麼好用的效果。淡然,這種效果也不要濫用在不合適的其餘地方,咱們能夠把當作一種加強效果是哦也能,好比幻燈片滾動效果這些,彷佛是不錯的選擇。固然,可能也有其餘方面的潛力,我沒想到的。
CSS 捕捉點使你可以與瀏覽器的本機滾動交互掛鉤,令界面達到無縫流暢的效果。隨着 可能的 JavaScript API 出現,這些功能將變得更增強大。
(正文完)
廣告時間(長期有效)
我有一位好朋友開了一間貓舍,在此幫她宣傳一下。如今貓舍裏養的都是布偶貓。若是你也是個愛貓人士而且有須要的話,不妨掃一掃她的【閒魚】二維碼。不買也沒關係,看看也行。
(完)