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;
}
透過這項簡單的新增功能,我們修正了 Chatbox 示範中的雙重拉動重新整理動畫,並改為實作使用更簡潔的載入動畫的自訂效果。當收件匣重新整理時,整個收件匣也會模糊處理:
以下是完整程式碼的程式碼片段:
<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="refresher">
<div class="loading-bar"></div>
<div class="loading-bar"></div>
<div class="loading-bar"></div>
<div class="loading-bar"></div>
</div>
<section id="inbox"><!-- msgs --></section>
<script>
let _startY;
const inbox = document.querySelector('#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.classList.contains('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
,要達到這個效果相當困難。