scrollbar-gutter: stable 能防止页面抖动,因其强制浏览器在布局阶段为滚动条预留固定宽度空间,使内容区宽度恒定;必须作用于 html 元素并配合 overflow-y: auto 才生效,不支持时应通过 @supports 回退至 overflow-y: scroll。

因为 scrollbar-gutter: stable 强制浏览器在布局阶段就为滚动条预留固定宽度空间,使内容区宽度不再随滚动条显隐而变化。
它不是隐藏或显示滚动条,而是提前“占位”
滚动条跳动的本质是:当内容溢出触发 overflow-y: auto 时,浏览器突然从内容区“抠走”约 15–17px 宽度来画滚动条,导致所有 width: 100% 元素向左偏移。而 scrollbar-gutter: stable 告诉浏览器:“不管现在要不要滚动,右侧这个槽(gutter)永远算进 padding-box,但不挤 content”。这个空间成了盒模型的一部分,布局计算时已固定。
为什么必须写在 html 上且配 overflow-y: auto
scrollbar-gutter 是规范限定的根滚动容器专属属性,只对 html 生效——写在 body、.main 或任何 div 上都会被静默忽略。同时,它不主动触发预留逻辑,必须搭配 overflow-y: auto(或 scroll)才能激活:
-
html { scrollbar-gutter: stable; }→ 无效果,缺少 overflow 触发条件 -
html { overflow-y: visible; scrollbar-gutter: stable; }→ 不激活 gutter -
html { overflow-y: scroll; scrollbar-gutter: stable; }→ 冗余,scroll已强制占位,旧 Safari 可能冲突 -
html { overflow-y: auto; scrollbar-gutter: stable; }→ 正确组合:滚动条按需出现,槽空间始终存在
@supports 回退到 overflow-y: scroll 才真正兜底
Chrome 94+、Firefox 97+、Safari 16.4+ 支持该属性,但微信内置 WebView、部分安卓 WebView、旧版 Edge 仍不支持。靠 JS 测量滚动条宽度或硬写 padding-right: 17px 都不可靠——macOS 隐藏滚动条时宽度为 0,Windows 主题可能为 12–20px。最稳方案是 CSS 层叠回退:
立即学习“前端免费学习笔记(深入)”;
html { overflow-y: scroll; }
@supports (scrollbar-gutter: stable) {
html { overflow-y: auto; scrollbar-gutter: stable; }
}
旧浏览器走第一行(常驻滚动条),新浏览器覆盖为按需 + 预留,零 JS、零运行时开销。
容易被忽略的是:Bootstrap Modal 等 UI 库会通过 JS 动态给 body 加 padding-right 补位,和 scrollbar-gutter 冲突,导致双重偏移。得额外加 body.modal-open { padding-right: 0 !important; } 覆盖。


















