531 字
3 分鐘

CSS Scroll Snap 怎麼避開固定導覽列:scroll-padding 與 scroll-margin

CSS Scroll Snap 很適合橫向卡片列、逐頁閱讀與章節導覽;實作後卻常出現一個更惱人的問題:捲動確實吸附了,但目標標題被固定導覽列蓋住。

關鍵是分清楚設定位置:scroll-snap-typescroll-padding 放捲動容器;scroll-snap-alignscroll-margin 放每一個吸附目標。 不要用 JavaScript 再算一次 header 高度來修正 CSS 本可描述的捲動邊界。

先建立真的能捲動的容器#

<div class="story-list">
<article class="story-card">第一段</article>
<article class="story-card">第二段</article>
<article class="story-card">第三段</article>
</div>
.story-list {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 85%;
gap: 1rem;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-padding-inline: 1rem;
}
.story-card {
scroll-snap-align: start;
}

Scroll Snap 的前提是容器有可捲動範圍。mandatory 會要求結束位置對齊 snap point;若讀者需要停在兩個項目間讀較長內容,可考慮 proximity,讓瀏覽器只在接近目標時吸附。

固定 header 用 scroll-padding-top#

頁面本身是捲動容器時,可把已知的 header 高度變成 scrollport 的內距:

:root {
--header-height: 4.5rem;
}
html {
scroll-snap-type: y proximity;
scroll-padding-top: var(--header-height);
}
article h2 {
scroll-snap-align: start;
}

這個設定也會影響 scrollIntoView() 與 fragment navigation 的可視對齊;它描述的是「容器的可用可視區域」,所以放在 html 或真正有 overflow 的面板,而不是隨意放到每個標題。

若只有某個錨點需要額外空間,例如 heading 上方有小型分類列,才在目標用 scroll-margin-top

#pricing {
scroll-margin-top: calc(var(--header-height) + 1rem);
}

輪播別只靠強制吸附#

Scroll Snap 解決的是捲動落點,不會替你補上輪播的可存取操作。若卡片是可互動內容,至少要讓鍵盤能移動到卡片內的連結或按鈕;不要把資訊只放在滑動才能看到的區塊。也要用實機檢查觸控板、鍵盤與 reduced motion 偏好下的感受。

如果問題是「呼叫 scrollIntoView() 後沒有捲到正確元素」,先確認你拿到的是單一 DOM element,而不是先把 CSS 吸附規則當成錯誤來源;可搭配 scrollIntoView 常見錯誤與定位方式 排查。

參考資料:

MDN:CSS Scroll Snap 基本概念

MDN:scroll-padding

CSS Scroll Snap 怎麼避開固定導覽列:scroll-padding 與 scroll-margin
https://laplusda.com/posts/css-scroll-snap-fixed-header/
作者
Zero
發佈於
2026-07-31
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

回報錯字、失效連結,或告訴我你想看的延伸主題。