滚动容器的尾部 padding 去哪了
给一个会横向滚动的 flex 容器加 padding: 0 20px,本意是首尾各留 20px。可在不少浏览器里,滚到最右时尾部那 20px 不见了——最后一项直接贴住容器右内边。根因是历史上浏览器计算可滚内容宽度(scrollWidth)时,只算到内容盒、把 padding-inline-end 排除在外,于是它落在滚不到的区域。这与居中即截断同属「flex + overflow 边界」,但那页是 justify-content: center 把首部推到负坐标,这页是尾部 padding 不计入可滚区。下面实测当前浏览器的真实表现。
1 · 滚到两端,实测首尾留白
容器设 padding: 14px 20px 且内容溢出。点按钮把它滚到最左 / 最右,用 getBoundingClientRect 量首项左缘、末项右缘到容器内边的可见距离:首部 20px 一般都在,尾部是否还在 20px 取决于本浏览器是否把 padding-inline-end 计入 scrollWidth。打开「末尾
spacer 修复」会在末尾插一个等宽占位,把那段留白塞进可滚内容里。
为什么是「尾部」而非「首部」。 滚动从 scrollLeft: 0 起算,首部 padding-inline-start 落在内容原点之前、天然在视野内;而 scrollLeft 的上限是
,一旦 scrollWidth 不含尾部 padding,最右就停在「最后一项右缘」,那 20px 永远滚不出来。CSSWG 已就此作出决议(#129,采用 Firefox 的「不计入」行为),但各引擎实现尚未收敛——所以本页以实测为准(核对于 2026-08)。
2 · 三种绕法
| 做法 | 效果 | 代价 |
|---|---|---|
末尾占位 (::after / spacer) |
在内容末尾插一个 flex: none 的等宽占位,把尾部留白变成真实可滚内容。 |
多一个无语义节点;::after 在 flex 容器上可直接当 item 用,无需改 DOM。 |
最后一项 margin-inline-end |
给末项加右外边距,同样计入可滚宽度。 | 需选中「最后一项」(:last-child),且 margin 也属可滚内容。 |
border 代替 padding |
用透明 / 同色 border-inline 留白,border 不受该问题影响。 |
滚动条位置随 OS 不同(可能压在 border 上),且 border 不能用百分比。 |
结论已定,实现未齐。 csswg-drafts #129 已有决议:采用 Firefox 的行为——没有任何元素会让滚动容器的 inline-end padding 计入可滚区(本页 lab 会实测当前浏览器的结果)。也就是说标准化的方向是「不计入」,上面三种绕法不是过渡手段而会长期有效,其中末尾占位兼容性最好、对 OS 滚动条无副作用;待观察的是 Chromium 与 WebKit 何时向该决议对齐(核对于 2026-08)。
3 · 延伸
- Flexbox and padding · chenhuijing.com — 本页问题的出处:滚动 flex 容器尾部 padding 丢失的来龙去脉,以及 border / 伪元素两种绕法。
- Scrollable overflow & padding · csswg-drafts #129 — 滚动容器是否应把 padding-inline-end 计入 scrollable overflow;已决议采用 Firefox 的「不计入」行为。