<p> { box-sizing: border-box } 不够用,必须显式声明 , ::before, ::after 和表单控件;伪元素默认 content-box 会撑开布局,旧版 Safari 中表单控件继承不稳定,JS 尺寸计算需适配 border-box 含边距逻辑。</p>
直接写 * 不能统一盒模型,必须显式包含伪元素和表单控件——否则布局会在 Safari、旧版 Chrome 或第三方组件中意外溢出。
通配符 * 只匹配真实 DOM 元素,不覆盖 ::before 和 ::after 生成的内容。而这些伪元素默认是 content-box,一旦你用它们画装饰边框、三角箭头或做布局辅助,padding/border 就会额外撑开容器。
::after { content: ""; display: block; width: 100%; height: 2px; },但底部多出滚动条或换行content-box 解析,2px 高度 + 自身 margin/padding(如有)叠加导致超限box-sizing: border-box,但你外层容器加了 padding 后又没重置,尺寸会二次膨胀这是最容易被跳过的三行代码,却是真正生效的最小完整集:
*, *::before, *::after {box-sizing: border-box;}
:host 或 style 标签内重复写一遍原生 <input>、<textarea>、<select>、<button> 在旧版 Safari(≤12)或部分 Android WebView 中,对 box-sizing 的继承行为不稳定——即使父级写了全局规则,它们仍可能按 content-box 渲染,造成光标偏移、高度塌陷或宽度不准。
input, textarea, select, button { box-sizing: border-box; }
input[type="text"] 这类细化选择器,会漏掉 type="email"、type="search" 等<circle>、<rect>)和替换元素(如 <img>)不受影响,但若设了 display: block 再加 padding,border-box 就会生效——这点常被忽略如果你代码里用了 element.offsetWidth、getBoundingClientRect() 或基于 clientWidth 做动态计算(比如弹窗定位、Tooltip 翻转、Canvas 映射),切换到 border-box 后,这些值代表的是「含 padding + border」的总宽,不再是 content-box 下的「纯内容宽 + 手动累加」。
box-sizing 规则,对比 offsetWidth 值变化,快速定位是否是它引发的问题真正难的不是写出那几行 CSS,而是后续有人加了 .legacy-widget { box-sizing: content-box !important; },或者某插件 CSS 漏写了伪元素——这种问题只在 Safari 上复现,还很难定位。