根本原因是浏览器默认采用 content-box 盒模型,width/height 仅指内容区,padding 和 border 额外计算;表单控件、flex 子项、getboundingclientrect() 时机、布局上下文及 shadow dom 等场景均受此影响。

根本原因不是你写错了,而是浏览器按 content-box 盒模型算的——width 和 height 只管内容区,padding 和 border 是额外加在外面的。
box-sizing 默认是 content-box,不是“总宽”
比如写了 .item { width: 200px; padding: 12px; border: 2px solid #333; },实际占位是 200 + 12 + 12 + 2 + 2 = 228px。这不是 bug,是 W3C 标准行为。
- 表单控件(
input、textarea、select)在多数浏览器里仍继承content-box,并带默认padding和border,并排时极易错位 - 用开发者工具选中元素,在 “Computed” 面板直接看
box-sizing值,别猜 - 第三方 UI 库(如旧版 Element UI)可能内部依赖
content-box,全局* { box-sizing: border-box; }会破坏其内边距表现
flex 子项写了 width 却不生效
在 display: flex 容器里,width 只是参考值,真正起效的是 flex-basis;如果没设,浏览器按内容宽度推导,再被 flex-shrink 压缩,视觉上就“变窄了”。
- 想固定宽度:用
flex: 0 0 200px(等价于flex-grow: 0; flex-shrink: 0; flex-basis: 200px) - 避免同时写
width和flex-basis,后者优先级更高,容易覆盖预期 -
min-width: 0要配合flex-basis: 0使用,否则图片或长文本可能撑开容器
getBoundingClientRect() 返回值和视觉不符
这个方法返回的是渲染后实际占位尺寸(含 padding、border、DPR 缩放),但如果你在 CSS 类名切换、媒体查询响应或异步属性更新(如 v-direction 动态加到 body)后立刻调用它,很可能拿到的是旧状态下的值。
- 典型场景:监听视频方向事件 → 异步修改
bodyclass → 立即调用getBoundingClientRect()→ 结果滞后 - 临时解法:加
setTimeout(() => { ... }, 0)或用requestAnimationFrame延迟到下一帧 - 更稳做法:监听
resize或使用MutationObserver检测关键 class 变化后再取值
表格、绝对定位、inline 元素让 width 失效
这些不是盒模型问题,而是布局上下文或 display 类型本身的限制。
- 表格:默认
table-layout: auto,width只是建议值;要强制按声明生效,得加table-layout: fixed且给table设明确width - 绝对定位:
position: absolute元素的width相对于最近的定位祖先,不是父容器;若父容器是static,它会一直往上找到html,宽高参考系就错了 - inline 元素(如
span):width和height完全无效;必须先改display: inline-block或block,但注意换行行为变化
最容易被忽略的是:Shadow DOM 和 CSS-in-JS 里,* 规则无法穿透作用域——box-sizing: border-box 得在对应 scope 内重复声明;还有伪元素(::before、::after)如果不显式包含,照样按 content-box 算,一不小心就撑破容器。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











