width不包含滚动条,因它仅定义内容区宽度;offsetwidth包含滚动条,因其反映元素实际渲染占位宽度,含border、padding及已渲染的滚动条像素。

不能强制 CSS 盒模型把滚动条宽度算进 width 声明里 —— 滚动条不是盒模型的“组成部分”,它只是渲染时附着在元素右侧(或底部)的 UI 组件,会从 content 区域内部或 padding 区域内“抠出”空间,但不改变你写的 width 值本身。
为什么 width 不包含滚动条,但 offsetWidth 却包含?
width 是样式属性,只控制内容区尺寸;而 offsetWidth 是 JS 读取的**实际渲染占位宽度**,包含 border + padding + content,也包含已渲染的滚动条所占据的像素 —— 因为滚动条是该元素渲染输出的一部分。这不是 bug,是浏览器一致行为(Chromium/Firefox/Safari 均如此)。
- 写
width: 300px→ 内容区就是 300px 宽,滚动条额外挤占空间 - 查
ele.offsetWidth→ 返回值 ≈ 300px + 左右 padding + 左右 border + 滚动条宽度(如果存在) - 查
ele.clientWidth→ 返回值 ≈ 300px + 左右 padding,但**自动减去滚动条宽度**
想让内容刚好填满、又不触发二次滚动,该用哪个值?
用 clientWidth,不是 offsetWidth,更不是硬写 calc(100vw - 17px)。
-
clientWidth直接给你“当前可用内容宽度”,含 padding、不含滚动条,拿来设子元素width最稳 - 必须等布局稳定后再读:放在
requestAnimationFrame回调里,或resize事件后 - IE 兼容要 fallback:
document.documentElement.clientWidth || document.body.clientWidth - 局部容器(如
overflow: auto的弹窗)要用自身ele.clientWidth,不是documentElement
scrollbar-gutter: stable 能替代 JS 吗?
不能替代,但能大幅降低对 JS 的依赖 —— 它的作用是**预留滚动条位置,避免出现/消失时 layout shift**。
- 加了
scrollbar-gutter: stable both后,即使内容没溢出,浏览器也会在右侧预留滚动条空间,clientWidth就不会突变 - 它不告诉你滚动条多宽,也不改变
width计算逻辑,只是让布局更可预测 - 目前仅 Chromium 120+ 和 Safari 17.4+ 支持,Firefox 尚未实现
- 搭配
box-sizing: border-box全局设置,能覆盖 80% 的意外溢出场景
滚动条宽度永远无法通过纯 CSS 获取,getComputedStyle 查不到;硬写固定像素值会在高 DPI 缩放、细滚动条、macOS overlay 模式下失效;真正需要精确适配时,唯一可靠路径是 JS 动态读取 clientWidth 或 offsetWidth - clientWidth。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











