CSS 与布局 / 🧲 Flexbox · 简写语义与对齐边界 / 滚动容器的尾部 padding 去哪了 待审核 12 / 14
overflow · padding 丢失

滚动容器的尾部 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 修复」会在末尾插一个等宽占位,把那段留白塞进可滚内容里。

图 1-1 · 滚到两端后量首项左缘与末项右缘到容器内边的可见距离,并可开关末尾占位修复。

为什么是「尾部」而非「首部」。 滚动从 scrollLeft: 0 起算,首部 padding-inline-start 落在内容原点之前、天然在视野内;而 scrollLeft 的上限是 scrollWidthclientWidthscrollWidth - clientWidth,一旦 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)。

图 2-1 · 三种绕法的代码对照。

3 · 延伸

  • Flexbox and padding · chenhuijing.com — 本页问题的出处:滚动 flex 容器尾部 padding 丢失的来龙去脉,以及 border / 伪元素两种绕法。
  • Scrollable overflow & padding · csswg-drafts #129 — 滚动容器是否应把 padding-inline-end 计入 scrollable overflow;已决议采用 Firefox 的「不计入」行为。