早些時候有看到過一個 純CSS輪播圖 的文章,當時有研究過實現,大概是利用了 hash
(錨標記) 和 scroll-snap
來實現的,但是具體實現已經回憶不起來了。
正好現在分享群組裡邊暫時沒有主題了,就想著可以當成一個常駐的補位小環節,大家一起瀏覽 CodePen 之類的社群找一個大家都感興趣的 Demo 來研究。
在分享前還是需要自己重新研究一遍的,不然在講述的時候出錯可太 “甜蜜的” 尷尬了。
首先呢,先實現一個簡易的的可控輪播示例
在樣例的實現中我將會使用到一下技術棧,希望你可以稍微瞭解一下
Pug
(HTML前處理器)Stylus
(CSS前處理器)
P.S.
以下筆記內容將逐步實現目標文章示例,會復原目標文章內的元素樣式,稍微有點改動但變化不大,因為自己想的樣式太醜了。
? 講解:
可以點開上方示例中的選項卡檢視實現程式碼,
- 在
html
中書寫了 5 個<div
並且宣告瞭對應的ID
; - 並且在後續新增了
<a>
標籤來改變URL當中的hash
值來控制卡片的切換; - 在
css
利用scroll-behavior:smooth
這個屬性,來達到切換卡片的平滑滾動效果。
但是缺少了切換前進後退按鈕,接下來我們就來實現這個功能:
? 講解:
其實很憨,直接為每一個卡片新增了前進後退按鈕的 <a>
標籤而已。
稍微有點麻煩的就是 如何讓這兩個按鈕隨著卡片的切換而改變,而不被後一個卡片的按鈕所覆蓋,因為這兩個按鈕是不會隨著卡片切換所移動的,這裡就需要腦洞大開了!
正常思路來說,肯定是會嘗試修改 前進後退按鈕 的父級的定位方式。
確實,會需要修改成 position:relative
,但是這個其實是為了每次切換卡片後變更對應的錨連結的。
原示例是從輪播元件的最外層容器建立了 ::before
和 ::after
兩個偽類,給他們設定的切換按鈕的樣式,並且設定為點選穿透,然後把輪播卡片內的 前進後退按鈕 為 透明
底色。
這樣所展示的 “按鈕” 就不會隨卡片所以移動了,而實際的切換按鈕會隨著卡片所移動,只是不會被瀏覽者發現。
功能基本實現了,然後我們復原一下原示例的樣式。
對照一下原示例,除了自動播放外還差了些什麼呢?emmmm.....自動播放!
? 尾關BOSS ? 自動輪播
最後來看一下她是如何實現自動播放的,這裡的實現方式如果他不講我直接就蒙圈了,但是確實很贊!?
- First I slowly offset the scroll snap points to the right, making the scroll area follow along due to being snapped to them.
首先我緩慢地將滾動捕捉點向右偏移,使滾動區域由於捕捉它們而跟隨。- After having scrolled the width of a whole slide, I deactivate the snapping. The scroll area is now untied from the scroll snap points.
在滾動整個幻燈片寬度後,我停用了捕捉。 滾動區域現在與滾動捕捉點解除繫結。- Now I let the scroll snap points jump back to their initial positions without them “snap-dragging” the scroll area back with them
現在我讓滾動捕捉點跳回到它們的初始位置,而不用它們 “捕捉拖動” 滾動區域- Then I re-engage the snapping which now lets the scroll area snap to a different snap point ?
然後我重新啟用捕捉,讓滾動區域捕捉到不同的捕捉點
看起來有點不易懂,但是其實並不複雜的。
其實就是利用了 scroll-snap
會使滾動容器的捕捉點變更為你設定的元素對齊位置(scroll-snap-align
),然後透過修改 left
屬性值使滾動容器向右滾動實現向後滾動的效果,然後透過修改當前元素的對齊位置為 none
, 讓滾動容器捕捉到下一個元素的對齊位置,以此來達到自動輪播的效果,那麼讓我們來實現一下吧!
但是我還沒有增加懸停停止自動輪播和一些其他的最佳化,有興趣的可以自己實現一下,用到的CSS屬性:
完整復現一下原示例吧!
尾聲
其實一開始我是不知道他如何實現的視差滾動的,結果在研究自動輪播的時候,突然就通了,所以就加上來了
透過 transform:translate3d()
給中間的元素,增加了 Z軸 屬性,使其脫離了平面 “懸浮” 在輪播卡片上,然後在最外層容器的 “輪播器” 設定了 perspective
指定了容器平面與 視窗 的 Z軸 距離。
但是有點問題,只有在自動播放動畫執行時才會體現出來,手動控制切換是感覺不出來的,因為手動滾動時無法應用 scroll-snap
。
⚡ 相容性
什麼?你問我相容性?友盡了啊!
別想了,scroll-snap
屬性都是 CR
階段,也就是候選,具體正式上線還有2個階段要走,
並且scroll-behavior
(平滑滾動)屬性 Safari 是不支援的,
"scroll-behavior" | Can I use
"scroll-snap" | Can I use
所以移動端的相容有很大問題,畢竟還有一個毒瘤 —— 微信內建瀏覽器,也是不支援這些屬性的,
我在製作的過程中都沒有考慮過移動端的適配,直接放棄了,PC端還是可以玩玩的。
自動輪播實現不了,那麼視差滾動也就沒辦法實現了,
鬧這麼大一圈,其實就是個圖個樂子,不過嘗一下鮮,學習到別人的腦洞就好了。
檔案連結
scroll-behavior - CSS | MDN
perspective - CSS | MDN
scroll-snap-type - CSS | MDN
scroll-snap-align - CSS | MDN
hover - CSS | MDN
:focus-within - CSS | MDN
prefers-reduced-motion - CSS | MDN
CSS-Only Carousel | CSS-Tricks
You can get pretty far in making a slider with just HTML and CSS | CSS-Tricks
大俠,請留步,要不過來瞭解下CSS Scroll Snap? « 張鑫旭-鑫空間-鑫生活
本文參與了SegmentFault 思否寫作挑戰賽,歡迎正在閱讀的你也加入。