TL;DR
CSS overscroll-behavior 屬性可讓開發人員在到達內容頂端/底部時,覆寫瀏覽器的預設溢位捲動行為。用途包括停用行動裝置的下拉更新功能、移除過度捲動發光和橡皮筋效果,以及防止頁面內容在互動視窗/疊加層下方捲動。
背景
捲動邊界和捲動鏈結
捲動是與網頁互動最基本的方式之一,但由於瀏覽器有奇特的預設行為,某些使用者體驗模式可能難以處理。舉例來說,假設應用程式導覽匣包含大量項目,使用者可能需要捲動瀏覽。當使用者捲動到最底部時,溢位容器會停止捲動,因為沒有更多內容可供瀏覽。換句話說,使用者會到達「捲動邊界」。但請注意,如果使用者繼續捲動,會發生什麼情況。抽屜式導覽面板後方的內容開始捲動!捲動功能會由父項容器接管,在範例中就是主頁面本身。
這種行為稱為捲動鏈結,是瀏覽器捲動內容時的預設行為。預設值通常很不錯,但有時可能不符合需求,甚至出乎意料。某些應用程式可能會想在使用者到達捲動邊界時,提供不同的使用者體驗。
下拉更新效果
下拉更新是 Facebook 和 Twitter 等行動應用程式普及的直覺式手勢。在社群動態消息中向下拉動並放開,即可騰出空間載入最新貼文。事實上,這種特殊的使用者體驗非常受歡迎,因此 Android 版 Chrome 等行動瀏覽器也採用了相同的效果。在頁面頂端向下滑動,即可重新整理整個頁面:
。
會重新整理整個頁面。
在 Twitter PWA 等情況下,停用原生下拉更新動作可能較為合適。這是因為在這個應用程式中,您可能不希望使用者不小心重新整理頁面。甚至可能看到雙重重新整理動畫!或者,您也可以自訂瀏覽器的動作,使其更符合網站的品牌形象。可惜的是,這類自訂功能很難實現。開發人員最後會編寫不必要的 JavaScript、新增非被動觸控事件監聽器 (會阻擋捲動),或將整個頁面固定在 100vw/vh <div> (防止頁面溢位)。這些解決方法對捲動效能有明確記載的負面影響。
我們一定可以做得更好!
隆重推出 overscroll-behavior
overscroll-behavior 屬性是一項新的 CSS 功能,可控制過度捲動容器 (包括頁面本身) 時的行為。您可以使用這個屬性取消捲動鏈結、停用/自訂下拉更新動作、停用 iOS 上的橡皮筋效果 (當 Safari 實作 overscroll-behavior 時) 等。最棒的是,使用 overscroll-behavior 不會像簡介中提到的駭客一樣,對網頁效能造成負面影響!
這個屬性有三個可能的值:
- auto:預設值。源自元素的捲動可能會傳播至祖系元素。
- contain:防止捲動鏈結。捲動不會傳播至祖系,但會顯示節點內的本機效果。例如 Android 上的過度捲動發光效果,或 iOS 上的橡皮筋效果,可在使用者達到捲動邊界時通知使用者。注意:在
html元素上使用overscroll-behavior: contain可防止過度捲動導覽動作。 - none:與
contain相同,但也會防止節點本身的過度捲動效果 (例如 Android 過度捲動發光或 iOS 橡皮筋效果)。
現在來看看幾個例子,瞭解如何使用 overscroll-behavior。
防止捲動動作逸出固定位置元素
聊天方塊情境
建議在頁面底部固定放置聊天方塊。我們的目的是讓聊天方塊成為獨立元件,並與後方的內容分開捲動。不過,由於捲動鏈結,使用者一看到即時通訊記錄中的最後一則訊息,文件就會開始捲動。
在這個應用程式中,比較適合的做法是讓聊天方塊內的捲動操作停留在聊天室內。只要將 overscroll-behavior: contain 新增至保留即時通訊訊息的元素,即可達成這個目標:
#chat .msgs {
overflow: auto;
overscroll-behavior: contain;
height: 300px;
}
基本上,我們是在聊天方塊的捲動內容和主頁面之間建立邏輯分隔。最終結果是,當使用者到達即時通訊記錄的頂端/底部時,主頁面會保持不變。在聊天方塊中開始的捲動不會向外傳播。
網頁重疊情境
「捲動下方」情境的另一種變化,是內容在固定位置疊加層後方捲動。必須給予明確的提示 overscroll-behavior!瀏覽器試圖提供協助,但最終卻讓網站看起來有錯誤。
範例:有和沒有 overscroll-behavior: contain 的互動視窗:
停用下拉更新功能
只要一行 CSS 程式碼,就能關閉下拉更新動作。只要防止在整個可視區域定義元素上進行捲動鏈結即可。在大多數情況下,這會是 <html> 或 <body>:
body {
/* Disables pull-to-refresh but allows overscroll glow effects. */
overscroll-behavior-y: contain;
}
只要加上這項簡單的設定,就能修正聊天盒示範中的雙重下拉更新動畫,並改為實作自訂效果,使用更簡潔的載入動畫。收件匣重新整理時,整個收件匣也會模糊處理:
以下是完整程式碼片段:
<style>
body.refreshing #inbox {
filter: blur(1px);
touch-action: none; /* prevent scrolling */
}
body.refreshing .refresher {
transform: translate3d(0,150%,0) scale(1);
z-index: 1;
}
.refresher {
--refresh-width: 55px;
pointer-events: none;
width: var(--refresh-width);
height: var(--refresh-width);
border-radius: 50%;
position: absolute;
transition: all 300ms cubic-bezier(0,0,0.2,1);
will-change: transform, opacity;
...
}
</style>
<div class="refre>she<r"
div class=&qu><ot;l>oad<ing-bar"/div
div>< cla>ss=<"loading-bar"></div>
<div class="loading><-bar>&<quot>;/<div
div class=&q><uot;loading><-bar&quo>t;</div
/>div
section id="inbox"!-- msgs --/section
script
let _startY;
const inbox = document.querySel>ector('#inbox');
inbox.addEventListener('touchstart', e = {
_startY = e.touches>[0].pageY;
}, {passive: true});
inbox.addEventListener('touchmove', e = {
const y = e.touches[0].pageY;
// Activate custom pull-to-refresh effects when at the top of the container&&
> // and &&user is scrolling up.
if (document.scrollingElement.scrollTop === 0 y _startY
!document.body.class<List.co>ntains('refreshing')) {
// refresh inbox.
}
}, {passive: true});
/script
停用過度捲動發光和橡皮筋效果
如要在達到捲動邊界時停用彈跳效果,請使用 overscroll-behavior-y: none:
body {
/* Disables pull-to-refresh and overscroll glow effect.
Still keeps swipe navigations. */
overscroll-behavior-y: none;
}
完整展示模式
總而言之,完整的聊天方塊示範會使用 overscroll-behavior 建立自訂下拉更新動畫,並停用捲動功能,避免捲動超出聊天方塊小工具。這能提供最佳使用者體驗,如果沒有 CSS overscroll-behavior,就很難達成。