先记住这个答案
区别在于 width 量的是哪一圈。content-box 是浏览器默认值,width 只算内容区,padding 和 border 另外往外加,所以写了 width: 200px 再加 padding: 20px 和 2px 边框,元素实际占 244px。border-box 下 width 就是到边框外沿的总宽,还是 200px,内容区缩成 156px。需要按设计稿写死尺寸、用百分比分栏、表单控件对齐时都优先选 border-box,多数项目直接在全局重置里设好。
content-box的外宽含边框和内边距border-box的宽度含边框和内边距- 默认盒模型是
content-box border-box可防内边距撑宽
同一组样式,两种算法的结果
拿一个最常见的场景:两个卡片各占 50%,再给卡片加点内边距。
.row { width: 400px; }
.card {
float: left;
width: 50%; /* 200px */
padding: 16px;
border: 1px solid #ddd;
}
/* content-box(默认):200 + 16*2 + 1*2 = 234px,两个 468px > 400px,第二个掉到下一行 */
/* border-box:总宽就是 200px,两个正好 400px,排在一行 */
.card { box-sizing: border-box; }content-box 下,百分比宽度和 padding 放在一起就会出问题:百分比算的是内容区,内边距又在外面加一圈,加起来一定超过 50%。以前的做法是用 calc(50% - 34px) 手动扣掉,改一次内边距就要改一次 calc,很容易漏。
换成 border-box,width: 50% 就是卡片看得见的宽度,内边距怎么改都不会撑破布局。
为什么大家都全局设 border-box
设计稿上标的尺寸,是一个按钮、一个输入框从边框到边框的宽度。border-box 的算法和人眼看到的一致,写 CSS 时不用再做加减法。
html { box-sizing: border-box; }
*, *::before, *::after { box-sizing: inherit; }用 inherit 而不是直接在 * 上写 border-box,是为了让某个第三方组件需要 content-box 时,只在它的根元素上改一次,里面的子元素会跟着继承。直接写 * { box-sizing: border-box } 也能用,只是局部回退要逐个元素覆盖。
- 表单控件本来就不统一
input、textarea、select、button在不同浏览器里的默认box-sizing并不一致,有的是border-box,有的是content-box。所以不设全局值时,同样width: 200px的输入框和按钮经常对不齐。全局统一成border-box顺手解决了这个问题。
content-box 还有什么用
content-box 也不是没用。当你关心的是内容区的尺寸,比如一张固定 300px 的图片外面包一层边框和内边距,希望图片区域始终是 300px,这时让 width 量内容区更直观。
另一种情况是维护老项目。整站本来按 content-box 写的尺寸,中途改成全局 border-box,所有带 padding 的元素都会变窄,需要全量回归,不能只改一行重置样式就上线。
容易答错的地方
- 以为
border-box也包含margin border-box只到边框为止,margin在两种模式下都不算进width。两个width: 50%的元素再各加margin: 0 8px,照样会超宽。这时要用gap、Flex 或者在calc里扣掉外边距。- 以为
border-box下内容区会被压成负数 - 内容区最小就是 0。如果
padding左右加起来 40px、border2px,而width只写了 30px,元素会被撑到 42px,不会出现负的内容宽度。 - 以为
height不受影响 box-sizing对height同样生效。border-box下height: 40px的按钮加了上下padding,总高还是 40px,文字区域变矮;content-box下按钮会变高。做按钮、输入框等高对齐时经常在这里踩坑。
面试官还会怎么问?
IE 怪异模式的盒模型是怎么回事?
老 IE 在怪异模式(页面没写 <!DOCTYPE>)下,width 就包含 padding 和 border,也就是现在的 border-box 算法。W3C 标准盒模型是 content-box。后来 CSS3 加了 box-sizing,让开发者可以自己选,才有了今天的全局 border-box 写法。
min-width、max-width 受 box-sizing 影响吗?
受。min-width、max-width、min-height、max-height 都按当前 box-sizing 解释。border-box 下 max-width: 600px 就是边框外沿最多 600px,这也是它在响应式里好用的原因。
在 Flex 布局里,flex-basis 按哪一圈算?
flex-basis 和 width 一样遵循 box-sizing。border-box 下 flex: 0 0 200px 的子项,边框到边框就是 200px;content-box 下还要再加上内边距和边框。Flex 子项宽度对不上时,先检查这个。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。