特別聲明,本文翻譯自@alligatorio的 Control Page Scroll in CSS Using Scroll Snapping一文,受限於譯者能力,譯文或存在不足,歡迎你們指出。如需轉載,煩請註明出處。
滾動捕捉「Scroll Snapping」是一項你確定已經見過的技術。當實現得不佳時,它會十分惹人厭,給用戶帶來不好的瀏覽體驗。但當實現得好的時候,它又會是用於實現展現內容的功能的好方法,如圖片畫廊。過去滾動捕捉只能經過JavaScript實現,但如今得益於新的CSS滾動捕捉模塊「 CSS Scroll Snap module」,這種效果已經能夠經過CSS實現了。
同時使人慶幸的是瀏覽器能夠根據用戶的滾動方式自動控制並判斷是否利用捕捉點「snap point」捕捉。這能夠避免捕捉點阻礙平滑導航這種很差的用戶體驗。css
讓咱們簡要介紹一下CSS中的滾動捕捉是如何工做的。html
與CSS grid或者Flexbox的使用相似,滾動捕捉的使用須要定義父級/容器元素,容器內的子元素會根據容器元素上定義的規則進行捕捉。web
Scroll Snapping的相關屬性中有一些是應用在容器元素上的,而另外一些則用於子元素。瀏覽器
容器元素上最重要的屬性就是scroll-snap-type
。它令一個普通元素成爲一個捕捉容器「snap container」元素,而且經過這個屬性能夠定義滾動捕捉軸「snap axis」(取值可爲:x
,y
,block
,inline
,both
),同時這個屬性還能夠定義滾動捕捉的嚴格性「strictness」(取值可爲:none
,proximity
,mandatory
).app
假設你想要某個容器在y軸上滾動,而且在任何狀況下都進行滾動捕捉,那麼你能夠這樣使用scroll-snap-type
屬性:flex
.container { scroll-snap-type: y mandatory; }
若是你想要在兩個方向上都進行滾動捕捉,而且捕捉行爲也不須要太過嚴格,那麼你能夠這樣寫:google
.container { scroll-snap-type: both proximity; }
另外一個做用於容器元素上的屬性是scroll-padding
,它容許爲容器設置padding,以免捕捉動做在容器的邊緣觸發。這個屬性的賦值語法與padding屬性的語法相同。flexbox
在滾動容器元素的子元素中,scroll-snap-align可能會是最重要的屬性。它能夠接收如下幾個值,none,start,end,center
,以指定元素是在開頭、中間、仍是結束時進行滾動捕獲。基於滾動軸,並假設當前爲從左到右的文本方向,那麼start能夠是頂部或左側,而end能夠是底部或右側。翻譯
你必需要設置元素的scroll-snap-align屬性值,由於它的初始值是none,這表示不會執行任何的捕捉。code
scroll-margin屬性的使用方式與margin屬性同樣,它能夠設置元素中的不一樣捕捉區域。
scroll-snap-stop屬性的取值能夠爲:normal
和always
,經過這個屬性能夠指定元素是否強制應用捕捉點,即便用戶的滾動行爲一般會致使跳過捕捉。這個屬性的初始值爲normal
。
接下來咱們再也不停留在理論和屬性介紹上,來經過一些簡單例子的演示一下吧。若是一個元素的滾動是基於y軸之上,且它的scroll strictness
被設置爲mandatory
,以下面的代碼所示:
<div class="container"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> </div>
.container { scroll-snap-type: y mandatory; overflow-y: scroll; border: 2px solid var(--gs0); border-radius: 8px; height: 33vh; } .container div { scroll-snap-align: start; height: 33vh; display: flex; justify-content: center; align-items: center; font-size: 4rem; } .container div:nth-child(1) { background: hotpink; color: white; } .container div:nth-child(2) { background: azure; } .container div:nth-child(3) { background: blanchedalmond; } .container div:nth-child(4) { background: lightcoral; color: white; }
那麼它的效果會像這樣:
相反地,將scroll strictness
屬性設置爲proximity
,那麼捕捉行爲將只會在snap point
的近距離範圍內發生。
.container { /* ... */ scroll-snap-type: y proximity; overflow-y: scroll; } /* ... */
最後,一塊兒來看一下當「snap snapping」在兩條軸上的滾動條上都產生的時候會是什麼樣子。圖片畫廊就是一個這種狀況下的完美用例,而咱們這裏的容器也剛好是一個網格容器。
首先,寫好HTML:
<div class="container2"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> <div>7</div> <div>8</div> <div>9</div> </div>
而後是樣式:
.container2 { display: grid; grid-template-columns: 100% 100% 100%; scroll-snap-type: both mandatory; overflow: scroll; border: 2px solid var(--gs0); border-radius: 8px; height: 33vh; } .container2 div { scroll-snap-align: start; height: 33vh; display: flex; justify-content: center; align-items: center; font-size: 4rem; } .container2 div:nth-child(1) { background: hotpink; color: white; } .container2 div:nth-child(2) { background: azure; } .container2 div:nth-child(3) { background: blanchedalmond; } .container2 div:nth-child(4) { background: lightcoral; color: white; } .container2 div:nth-child(5) { background: rebeccapurple; color: white; } /* ...你懂得 */
而後實現效果以下:
這篇文章淺顯地向你們介紹了一些語法知識,若是你有興趣瞭解更多的用例和查看更多示例,下面有幾篇不錯的文章。