必须写::before和::after,因为伪元素不继承box-sizing,默认仍为content-box,漏写会导致装饰性内容撑开容器;表单控件需单独声明以兼容旧版safari,svg及替换元素需谨慎使用。

直接在 CSS 开头加 *, *::before, *::after { box-sizing: border-box; } 就能统一所有元素的盒模型,这是现代前端项目的标准起手式。
为什么必须写 *::before 和 *::after
伪元素(如 ::before 和 ::after)默认不继承父元素的 box-sizing,它们走的是浏览器默认的 content-box。如果你只写 * { box-sizing: border-box; },这些伪元素仍可能在某些布局中“偷偷撑开”容器——比如用伪元素做三角箭头、装饰边框时,尺寸计算会意外偏离预期。
-
* { box-sizing: border-box; }覆盖不了伪元素,因为伪元素不是真实 DOM 节点,不匹配* -
*::before, *::after是独立选择器,必须显式声明才能生效 - 漏掉它们是很多“明明设了 border-box 却还在换行/溢出”的真实原因
哪些元素不能无脑套用 border-box
全局设置后,<input>、<textarea></textarea>、<select></select> 等表单控件在旧版 Safari(≤12)或某些 Android WebView 中,box-sizing 行为不稳定:边框渲染错位、光标偏移、甚至输入框高度塌陷。这不是 bug,而是这些控件原生 UI 层对 border-box 的支持不完整。
- 推荐单独重置:
input, textarea, select, button { box-sizing: border-box; }—— 显式声明反而更稳 - 避免用通配符覆盖 SVG 内部
<rect></rect>、<circle></circle>等图形元素;它们的width/height语义是坐标系尺寸,不是布局盒子 -
<img>、<video></video>等替换元素不受影响,但若设了display: block后加padding,border-box就会生效——这点常被忽略
box-sizing 切换会破坏 JS 尺寸读取逻辑
如果你的代码里用了 element.offsetWidth、getBoundingClientRect() 或基于 clientWidth 做动态计算(比如拖拽缩放、弹窗定位),切换到 border-box 后,这些值会变小——因为现在它们返回的是“含 padding + border”的总宽,而不是 content-box 下的“纯内容宽 + 额外累加”。这不会报错,但会让计算结果偏移。
- 检查所有涉及尺寸判断的 JS:特别是表单校验提示位置、Tooltip 自动翻转、Canvas 绘图区域映射
- 不要在
:hover或动画中动态切换box-sizing:transition对它无效,只会触发 layout thrashing - 调试技巧:在 DevTools 里临时删掉全局规则,对比
offsetWidth值变化,快速定位是否是它导致的偏差
真正麻烦的不是加那三行 CSS,而是加完之后忘了它已永久改写了所有 width/height 的语义——后续每个 padding、border、甚至 JS 读取尺寸的行为,都得按新规则重新理解。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











