透過 CSS 捲動 Snap 妥善控制捲動功能

宣告捲動自動對齊位置,打造精心控制的捲動體驗。

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

CSS 捲動 Snap 功能可讓網頁開發人員宣告捲動間距位置,建立可妥善控制的捲動體驗。分頁文章和圖片輪轉介面是兩個常用的範例。CSS Scroll Snap 提供簡單易用且一致的 API,可用來建構這些常見的使用者體驗模式。

背景

捲動貼齊情況

捲動是互動網路內容的熱門且自然的方式。由於這項工具的原生方法比一次顯示更多的資訊,因此對於螢幕空間有限的行動平台來說尤其重要。因此,網路作者越來越偏好將內容整理到可捲動的平面清單中,而不是深層階層。

捲動的主要缺點是缺乏精確度。在極少數的情況下,捲動畫面最終會對齊段落或句子。在頁面或圖片中央的捲動完成時,因為頁面或圖片的捲動完成而部分顯示,而包含有意義的邊界分頁或項目化內容,這種行為會更加明顯。這些用途適用於妥善控管的捲動體驗。

網頁開發人員長期以來一直依賴以 JavaScript 為基礎的解決方案來控制捲動,以解決這個缺點。然而,以 JavaScript 為基礎的解決方案無法提供完整的保真度解決方案,因為缺乏捲動自訂基元,或存取複合捲動的存取權。CSS 捲動 Snap 提供快速、高保真度且易於使用的解決方案,且能在不同瀏覽器間保持一致。

CSS 捲動 Snap 可讓網頁作者使用邊界,標示每個捲動容器的邊界,以便完成捲動作業。瀏覽器會根據捲動作業的細節、捲動容器的版面配置和顯示設定,以及貼齊位置的詳細資料,選擇最適合的結束位置,然後以流暢的動畫效果前往該位置。回到先前的範例,當使用者完成捲動輪轉介面後,可見圖片會自動套用到適當位置。JavaScript 不需要調整捲動畫面。

使用 CSS 捲動快照功能與圖片輪轉介面的範例。
使用 CSS 捲動貼齊功能與圖片輪轉介面。這裡的捲動自動對齊功能可確保在捲動結束時,圖片的水平中心會與捲動容器的水平中心對齊。

CSS 捲動固定

捲動貼齊功能是指調整捲動容器的捲動偏移,在捲動作業完成後延至偏好的「snap 位置」

您可以使用 scroll-snap-type 屬性,讓捲動容器選擇捲動貼齊功能。這會告知瀏覽器應考慮將此捲動容器貼至其子系產生的貼齊位置。scroll-snap-type 會決定捲動的軸:xyboth,以及間距嚴格程度:mandatoryproximity。稍後會再詳細討論。

您可以在元素上宣告所需的對齊方式,產生貼齊位置。這個位置是捲動偏移量,其中最近的祖系捲動容器和元素會依照指定的軸對齊。每軸可能的對齊方式如下:startendcenter

start 對齊表示捲動容器貼齊通訊埠起始邊緣應與元素貼齊區域起始邊緣對齊。同樣地,endcenter 對齊表示捲動容器的貼齊通訊埠結束邊緣或中心,應與元素貼齊區域的結束邊緣或中心對齊。

水平捲動軸上的各種對齊方式範例。

以下範例說明如何使用這些概念。

捲動貼齊功能的常見用途是圖片輪轉介面。舉例來說,如要建立水平圖片輪轉介面,讓系統在捲動時自動將圖片對齊,我們可以指定捲動容器在水平軸上具有強制 scroll-snap-type。將每張圖片設為 scroll-snap-align: center,確保系統會將圖片對齊輪轉介面中的圖片。

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;
}

#gallery img {
   scroll-snap-align: center;
}
<div id="gallery">
  <img src="cat.jpg">
  <img src="dog.jpg">
  <img src="another_cute_animal.jpg">
</div>

由於貼齊位置與元素相關聯,因此貼齊演算法可根據元素和捲動容器大小,聰明地決定貼齊時機和方式。舉例來說,假設某張圖片大於輪轉介面。簡單的對齊演算法可能會導致使用者無法平移畫面來查看完整圖片。不過,這項規格需要實作來偵測這個情況,並允許使用者自由捲動圖片,僅在圖片邊緣對齊。

查看產品示範 | 來源

範例:歷程產品頁面

捲動貼齊功能的另一個常見情況是頁麵包含多個邏輯區段,藉此垂直捲動畫面,例如一般產品頁面。scroll-snap-type: y proximity; 更適合這類情況。這不會幹擾使用者捲動至特定區段的中間,但會在捲動夠近的新區段時貼合並引人注意。

做法如下:

article {
  scroll-snap-type: y proximity;
  /* Reserve space for header plus some extra space for sneak peeking. */
  scroll-padding-top: 15vh;
  overflow-y: scroll;
}
section {
  /* Snap align start. */
  scroll-snap-align: start;
}
header {
  position: fixed;
  height: 10vh;
}
<article>
  <header> Header </header>
  <section> Section One </section>
  <section> Section Two </section>
  <section> Section Three </section>
</article>

捲動邊框間距和邊界

產品頁面的頂端標題設有固定位置。設計師也要求在捲動容器對齊時,讓部分頂端區塊保持可見,以便向使用者提供上方內容的設計提示。

scroll-padding 屬性是新的 CSS 屬性,可用於調整捲動容器 (或 snapport) 的有效可視區域,用於計算捲動對齊方式。屬性會根據捲動容器的邊框間距方塊定義插邊。在本範例中,我們在頂端新增了 15vh 額外內嵌,指示瀏覽器將捲動容器頂端邊緣下方的 15vh 視為捲動自動對齊的垂直起始邊緣。當系統進行對齊時,對齊目標元素的起始邊緣會與這個新位置對齊,因此會在頂端留出空間。

scroll-margin 屬性會定義用來調整貼齊目標有效方塊的輸出量,類似於貼齊捲動容器上的 scroll-padding 函式。

您可能已經注意到,這兩個屬性包含「snap」一詞,這是刻意為之,因為這些方法實際上會修改所有相關捲動作業的方塊,而非只調整捲動自動對齊。舉例來說,Chrome 會在計算分頁捲動作業 (例如 PageDown 和 PageUp) 的頁面大小時,以及計算 Element.scrollIntoView() 作業的捲動量時,將這些值納入考量。

查看示範 | 來源

與其他捲動 API 互動

DOM 捲動 API

捲動精確對齊會在所有捲動作業「之後」發生,包括由指令碼啟動的作業。使用 Element.scrollTo 等 API 時,瀏覽器會計算作業的預期捲動位置,然後套用適當的對齊邏輯,找出最終對齊位置。因此,使用者指令碼不需要進行任何手動計算,即可完成對齊。

順暢捲動

流暢捲動可控製程式輔助捲動作業的行為,捲動貼齊功能則決定目的地。由於這兩個屬性控制捲動的不同面向,因此可同時使用,並相輔相成。

過度捲動行為

「Overscroll 行為 API」可控制捲動在多個元素間的鏈結方式,且不受捲動間距的影響。

注意事項與最佳做法

目標元素之間的間距過大時,請避免使用強制貼齊功能。這可能會導致使用者無法存取位於貼齊位置之間的內容。

在多數情況下,您無需特徵偵測,即可將捲動間距新增為強化效果。如有需要,請使用 @supportsCSS.supports 偵測 CSS 捲動快照的支援情形。避免使用也存在於已淘汰規格中的 scroll-snap-type

CSS 功能偵測

@supports (scroll-snap-align: start) {
  article {
    scroll-snap-type: y proximity;
    scroll-padding-top: 15vh;
    overflow-y: scroll;
  }
}

在 JavaScript 中偵測功能

if (CSS.supports('scroll-snap-align: start')) {
  // use css scroll snap
} else {
  // use fallback
}

請勿假設透過程式輔助捲動 API (例如 Element.scrollTo) 一律會在要求的捲動偏移位置完成。捲動貼齊功能可在程式輔助捲動完成後調整捲動偏移。請注意,即使在捲動貼齊之前捲動貼齊,這仍不是個假設,因為捲動操作可能會因其他原因而中斷,但尤其在出現捲動貼齊情形的情況下更是如此。

日後作業

捲動體驗是 Chrome 團隊近期問卷調查的重點。這項調查結果指出,有幾個領域需要額外努力,才能縮小外掛程式程式庫和 CSS 之間的差距。我們接下來的工作將著重於 scroll-snap,包括:

  1. API 可用性和瀏覽器相容性。
  2. 著手使用 scroll-start新 CSS API
  3. 處理 snapChanged()新的 JS 事件