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

宣告捲動貼齊位置,建立精確控制的捲動體驗。

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

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

背景

捲動貼齊的用途

捲動是一種很熱門且自然的方式與網頁內容互動的方式。相較於一次只在畫面上看到資訊,平臺本身能夠提供更多資訊,對行動裝置平台而言尤其重要。因此,網頁作者越來越常將內容整理成可捲動的平面清單,而不是深度的階層。

捲動的主要缺點是缺乏精確性。很少是在與段落或句子上對齊的捲動畫面當頁面或圖片中間的捲動完畢,導致部分可見的內容,就會以更明顯的邊界顯示分頁或項目化內容。這些用途受益於受到妥善控制的捲動體驗。

網頁程式開發人員長期仰賴以 JavaScript 為基礎的解決方案來控制捲動,藉此解決這個短缺的問題。然而,JavaScript 解決方案缺少捲動自訂原始物件或複合式捲動功能的存取權,因此無法提供完整的保真解決方案。CSS Scroll Snap 能夠提供快速、高保真度且易於使用的解決方案,能在不同瀏覽器中保持一致。

CSS Scroll 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 屬性,可用於調整捲動容器的有效可視區域或快門,用於計算捲動貼齊對齊方式。這個屬性會定義捲動容器的邊框間距方塊的插邊。在我們的範例中,已在頂端新增額外的 15vh 插邊,藉此指示瀏覽器將較低位置 (位於捲動容器頂端邊緣的 15vh) 視為較低位置,做為捲動貼齊的垂直起始邊緣。貼齊目標時,貼齊目標元素的起始邊緣會隨這個新位置清除,因此會在上方留下空間。

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

您可能已註意到,這兩個屬性並未包含「snap」一詞。此為刻意設計,因為這類人員實際上會修改所有相關捲動作業的方塊,而非只是捲動貼齊作業。舉例來說,Chrome 計算分頁捲動作業 (例如 PageDown 和 PageUp) 的頁面大小,以及計算 Element.scrollIntoView() 作業的捲動量時,就會將這些密碼納入考量。

查看示範 | 來源

與其他捲動 API 互動

DOM Scrolling API

在所有捲動作業 (包括指令碼啟動的作業) 之後,才會發生捲動貼齊的情形。當您使用 Element.scrollTo 等 API 時,瀏覽器會計算預期的作業捲動位置,然後套用適當的貼齊邏輯,找出最終對齊位置。因此,使用者指令碼不需要手動計算貼齊。

順暢捲動

順暢捲動可控管程式輔助捲動作業的行為,捲動貼齊則會決定其目的地。由於這些元件控制捲動的方向性元素,因此可以搭配使用,並相輔相成。

過度捲動行為

過度捲動行為 API 可控制捲動跨多個元素鏈結的方式,不受捲動間隔影響。

注意事項與最佳做法

當目標元素相距很大時,請避免使用強制貼齊功能。這可能會導致暫時無法閱讀貼齊位置之間的內容。

在許多情況下,可以新增捲動滑動做為強化,而不需要功能偵測。如有需要,請使用 @supportsCSS.supports 偵測是否支援 CSS 捲動 Snap。 請避免使用已淘汰規格中的 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. 處理新的 CSS API,例如 scroll-start
  3. 處理新的 JS 事件,例如 snapChanged()