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

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

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

CSS 捲動貼齊功能可讓網頁開發人員宣告捲動貼齊位置,藉此打造精心控管的捲動體驗。分頁文章和圖片輪轉介面就是兩個常見的例子。CSS Scroll Snap 提供簡單易用且一致的 API,可用於建構這些熱門的使用者體驗模式。

背景

捲動自動對齊的用途

捲動是互動網路內容的熱門且自然的方式。這是平台提供比螢幕上一次顯示更多資訊的本機方式,在螢幕空間有限的行動平台上尤其重要。因此,網頁作者越來越偏好將內容整理成可捲動的扁平清單,而非深層階層。

捲動的最大缺點是缺乏精確度。捲動畫面很少會與段落或句子對齊。對於具有明確邊界且分頁或項目化的內容而言,當捲動完成時,畫面或圖片會停留在畫面中間,因此部分內容會顯示在畫面上。這些用途可從受控良好的捲動體驗中受益。

網頁開發人員長期以來一直依賴以 JavaScript 為基礎的解決方案來控制捲動,以解決這個缺點。不過,由於缺乏捲動自訂原始碼或存取複合捲動功能,以 JavaScript 為基礎的解決方案無法提供完整的保真度解決方案。CSS 捲動精確修正可確保提供快速、高保真度且易於使用的解決方案,並在各瀏覽器中一致運作。

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

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

CSS 捲動固定

捲動自動對齊是指在捲動作業完成後,調整捲動容器的捲動偏移量,使其位於偏好的自動對齊位置

您可以使用 scroll-snap-type 屬性,選擇讓捲動容器進行捲動自動對齊。這會告訴瀏覽器,應將此捲動容器的固定位置設為子項產生的固定位置。scroll-snap-type 會決定捲動軸線:xyboth,以及對齊精確度:mandatoryproximity。稍後會再詳細說明。

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

start 對齊表示捲動容器的 Snapport 開始邊緣應與元素固定區域的開始邊緣對齊。同樣地,endcenter 對齊方式表示捲動容器的 Snapport 終點邊緣或中心,應與元素 Snap 區域的終點邊緣或中心對齊。

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

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

捲動自動對齊的常見用途是圖片輪轉介面。舉例來說,如要建立水平圖片輪轉介面,並在捲動時將圖片吸附到每張圖片,我們可以指定捲動容器在水平軸上具有強制 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 Scrolling API

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

順暢捲動

平順捲動功能可控制程式化捲動作業的行為,而捲動自動調整功能則可決定其目的地。由於這兩個屬性控制捲動的不同面向,因此可同時使用,並相輔相成。

過度捲動行為

超出捲動行為 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 事件