1665 字
8 分鐘

CSS overflow: auto clip 怎麼用?單軸捲動與 sticky 邊界

很多水平卡片、表格或畫布元件,其實只需要左右捲動;但常見的 overflow: auto 會讓上下軸也成為可捲動軸,overflow: hidden 又可能讓 position: sticky 找到你不想要的祖先。結果就是 header 不再貼住預期位置,或觸控手勢在巢狀容器間互相搶事件。

直接答案是:水平元件先用 overflow: auto clip 表達「x 軸可捲動、y 軸只裁切」;針對要允許斜向手勢的地圖或放大圖片,再評估 scroll-axis-lock: none。兩者目前都不該被當成所有瀏覽器都已支援的 production 基線。

Chrome 153 release notes 將 single-axis scroll containers 標示為非穩定 channel 功能;scroll-axis-lock 也來自 CSS Overflow Level 5 的新規範。請把 feature detection、fallback 與真實裝置測試一起納入元件設計。

先分清楚三種 overflow 意圖#

寫法主要意圖常見代價
overflow: auto兩軸都可能需要捲動產生不必要的第二個 scroll axis,sticky 邊界較難推理
overflow: hidden隱藏溢出內容可能建立你不想要的滾動祖先,且鍵盤或程式捲動行為容易被誤判
overflow: auto clip一軸可捲動,另一軸裁切新語法仍需檢查瀏覽器支援與 fallback

這不是把內容「藏起來」的視覺技巧,而是把 scrollability 寫進 layout contract。你要先決定哪一個軸真的可以被使用者操作,再選擇 CSS。

水平卡片用 auto clip#

先建立不依賴特定框架的 HTML:

<section class="board" aria-labelledby="board-title">
<h2 id="board-title" class="board__title">功能總覽</h2>
<div class="board__track">
<article class="card">第一張卡片</article>
<article class="card">第二張卡片</article>
<article class="card">第三張卡片</article>
</div>
</section>

如果是整個 board 負責水平捲動,最小配置可以是:

.board {
overflow: auto clip;
overscroll-behavior-inline: contain;
}
.board__track {
display: flex;
gap: 1rem;
inline-size: max-content;
min-inline-size: 100%;
}
.card {
flex: 0 0 min(80vw, 24rem);
}

overflow shorthand 的兩個值分別對應物理 x 軸與 y 軸,不隨 LTR/RTL 或 writing mode 交換;auto clip 因此代表 x 可捲動、y 裁切。若元件需要支援不同 writing mode,請把這段意圖改寫成 overflow-inline: auto 與 overflow-block: clip,並實際檢查瀏覽器對 logical properties 的支援。

如果內容只應該在 x 軸移動,也可以把物理軸寫得更直白:

.board {
overflow-x: auto;
overflow-y: clip;
}

這種寫法適合先表達設計意圖,但不能跳過 @supports 與 fallback 測試;新舊瀏覽器對「一軸 scrollable、另一軸 clip」的處理可能不同。

為什麼它能幫 sticky 少走錯路#

position: sticky 不是固定在 viewport;它會受祖先的 scroll container、inset 與可用空間限制。當外層只因為 overflow: auto 意外建立 y 軸 scroll container,sticky header 可能就跟著錯誤的祖先計算。

一個簡化的 header 範例:

.board__title {
position: sticky;
inset-block-start: 0;
z-index: 1;
background: Canvas;
}

auto clip 的價值,是讓 layout 明確表示某一軸只能裁切,瀏覽器才有機會把 sticky 的不同軸邊界分開計算。但它不會自動修好所有 sticky 問題;仍要檢查祖先是否有 transform、contain、額外的 overflow、固定高度與 stacking context。

排錯時先在 DevTools 逐層暫時移除 overflow,再確認是哪一個祖先在目標軸真的可捲動。不要只把 z-index 調大,因為那通常解不了錯誤的 scroll ancestor。

scroll-axis-lock 適合另一種互動#

瀏覽器常會把觸控捲動手勢鎖到主要移動軸,避免使用者想左右滑時不小心上下漂移。CSS Overflow Level 5 的 scroll-axis-lock 允許作者在需要「斜向也能持續捲動」的 scroll container 上關閉這個鎖定:

.map-or-zoomed-image {
scroll-axis-lock: none;
}

這比較適合地圖、放大圖片或需要同時操作兩軸的畫布,不是一般水平 carousel 的預設值。普通卡片列通常應保留軸向鎖定,讓觸控操作更容易預期。

Feature detection 與 fallback#

先保留可操作的 fallback。下方 @supports 只能確認宣告是否被接受,不能單獨驗證單軸捲動:

.board {
overflow-x: auto;
overflow-y: hidden;
}
@supports (overflow: auto clip) {
.board {
overflow: auto clip;
}
}
@supports (scroll-axis-lock: none) {
.map-or-zoomed-image {
scroll-axis-lock: none;
}
}

fallback 使用 hidden 時,語意不等同於 clip;它可能仍參與 scroll container 計算。因此 fallback 的目標是讓舊瀏覽器能操作,而不是假裝兩種行為完全一樣。若 sticky 是核心需求,請在 fallback browser 上單獨驗收 header 邊界。

語法通過之後,還要看 clip 有沒有變成 hidden#

MDN 的 overflow 計算值規則記載:當另一軸不是 visible 或 clip,clip 會計算成 hidden。因此,既有實作也可能接受 overflow: auto clip 的語法,卻仍以 auto hidden 運作。僅看 @supports 成立,會把語法支援誤當成新的單軸行為。

Chrome 153 公告的單軸功能改變的是可捲動值與 clip 搭配的行為;公告連結的 CSSWG 修訂也處理各軸的 scroll container 邊界。本文沒有實測各瀏覽器,不能列出哪個穩定版本已符合全部行為。

可在實際測試頁的 DevTools Console 檢查文章範例:

const board = document.querySelector('.board');
if (!board) throw new Error('找不到 .board 測試元素');
const style = getComputedStyle(board);
console.table({
acceptsSyntax: CSS.supports('overflow', 'auto clip'),
computedX: style.overflowX,
computedY: style.overflowY,
writingMode: style.writingMode,
});

這段是尚未執行的瀏覽器診斷示例。如果語法為 true,但 computedY 是 hidden,就不能以它證明 y 軸仍是 clip。若 computedY 是 clip,也還要檢查真正溢出的內容、捲動操作及 sticky:沒有溢出時畫面不動,並不是功能成立的證據;其他樣式規則也可能蓋掉目標宣告。

依序記錄「宣告是否接受 → computed value → 實際操作」,才有可交接的相容性結果。若某個目標瀏覽器仍採舊行為,讓 sticky header 留在水平 track 的捲動元素外,是可以另外驗收的降級結構;不要依靠同一個語法查詢強迫啟用實驗行為。

上線前的四組測試#

  1. 滑鼠與觸控:水平拖曳不會把頁面垂直位置帶走;需要雙軸的地圖仍能斜向操作。
  2. 鍵盤:focus 進入卡片後,Tab、方向鍵與可見 focus ring 都能到達被裁切內容。
  3. sticky:在短內容、長內容、巢狀 overflow、縮放與不同 viewport 高度逐一檢查。
  4. 支援矩陣:至少測試 stable browser、Chrome 153 對應的實驗 channel、iOS/Android 觸控與沒有新語法的 fallback。

如果元件還需要 snap、marker 或按鈕導覽,可以接著看 CSS Scroll Marker 建立可存取輪播導覽;不要把實驗中的 marker API 與單軸 overflow 當成同一個功能。

參考資料:

Chrome for Developers:Chrome 153 release notes

W3C CSS Overflow Module Level 5:Scroll Axis Locking

MDN:CSS overflow carousels

MDN:overflow 計算值

MDN:CSS.supports()

CSSWG:各軸 scroll container 修訂 #13903

CSS overflow: auto clip 怎麼用?單軸捲動與 sticky 邊界
https://laplusda.com/posts/css-single-axis-scroll-container/
作者
Zero
發佈於
2026-09-12
許可協議
CC BY-NC-SA 4.0