你有沒有遇過這種情況?網頁跳出一個對話框,你想滑動看看裡面的內容,結果才滑到底,整個後面的網頁竟然也跟著動了起來!
或是,你在手機上瀏覽一個很酷的 Web App,只是想上下滑動一下,結果不小心觸發了瀏覽器的「下拉重新整理」,整個頁面就這樣重載了...
這種「滾動失控」的狀況,我們稱之為「滾動穿透 (Scroll Chaining)」。 過去要處理這種問題,可能需要動用一些 JS,甚至搞得有點複雜。
但好消息是,現在我們有了一個純 CSS 的新解法:overscroll-behavior
。
本篇同步發表於我的 Hashnode 部落格:
Eva Chen | 網頁設計師下班後 (hashnode.dev)
在我們深入 overscroll-behavior
之前,先來搞懂它要解決的問題。
「滾動穿透」或稱為「滾動鏈」,是瀏覽器的預設行為。 想像一下網頁上有兩個可以滾動的區域,一個是外層的整個頁面 (<html>
),另一個是內層的 <div>
(例如對話框、側邊欄、聊天視窗等)。
當你在內層的 <div>
裡滾動,滑鼠滾輪滾到底部(或頂部)後,如果繼續朝同一個方向滾動,這個「滾動事件」就會像接力棒一樣,傳遞給外層的 <html>
,導致整個頁面也開始滾動。
(這就是惱人的滾動穿透)
雖然這是瀏覽器的「貼心」設計,但在很多 UI 設計中,這反而會干擾使用者體驗,讓使用者覺得介面不聽話、很難控制。
overscroll-behavior
:你的滾動行為管理大師overscroll-behavior
這個 CSS 屬性,就是用來控制當一個元素滾動到邊界後,接下來會發生什麼事。 它可以讓你輕鬆地「切斷」滾動鏈,告訴瀏覽器:「這個框框滾到底了,就停在這裡,不要再去動後面的東西了!」
它有三個主要的屬性值:
auto
(預設值) 這就是我們前面說的預設行為,允許滾動穿透。滾動事件會一路向上傳遞。
contain
這大概是你最常用的值!它會阻止滾動穿透,也就是滾動事件會被「抑制」在當前的元素內。 不過,元素本身的「邊界效果」還是會保留,例如在手機上滾到底部時,那個小小的「回彈」(bounce) 效果依然存在。
none
最強力的選項!它不但會阻止滾動穿透,還會順便禁用元素本身的邊界效果。 例如,在手機上那個「下拉重新整理」或「回彈」效果,通通都會被取消。
你也可以分開設定 X 軸和 Y 軸的行為,例如 overscroll-behavior-x: none;
或 overscroll-behavior-y: contain;
。
說了這麼多,我們來看看實際怎麼用吧!
這大概是 overscroll-behavior
最經典的應用了。
我們只需要在一開始的這個範例中可以滾動內容的那個對話框容器上,加上一行 CSS:
.scrollable {
overflow: auto; /* 讓內容可以滾動 */
overscroll-behavior: contain; /* 加上這行 */
}
就可以了!現在當你在對話框裡的 .scrollable
裡面滾動時,就算滾到最頂部或最底部,背景的 <html>
也不會再跟著亂動了,他們兩者的滾動從此互不相關。
在開發 Web App 或一些沉浸式體驗的網頁時,瀏覽器預設的「下拉重新整理」功能可能會變得很礙事。我們不希望使用者只是想滑動頁面,卻不小心觸發了整個頁面重載。
這時候,我們可以對整個頁面下手:
html {
overscroll-behavior-y: none;
}
把 overscroll-behavior-y
設定為 none
,就可以有效地阻止手機瀏覽器預設的下拉重整手勢。
DEMO 連結:Prevent Pull-to-Refresh on Mobile with Overscroll Behavior
(請用手機打開 CodePen DEMO 的 Debug Mode 試試看)
overscroll-behavior
是一個非常實用且能大幅提升使用者體驗的 CSS 屬性。它解決了長久以來需要靠 JS 才能搞定的「滾動穿透」問題,讓我們能用更簡單的方式來管理網頁的滾動行為。
延伸閱讀:
感謝看到最後的你,若你覺得獲益良多,請不要吝嗇給我按個喜歡。❤️
如果你喜歡我的創作,還想看看其他有趣的分享與日常,
可以追蹤我的 IG @im1010ioio,或者是🧋送杯珍奶鼓勵我,謝謝你🥰。