盒模型与 box-sizing
基于 CSS 现代标准 · 核于 2026-06
速查
- 四层(由内向外):内容盒 → 内边距盒(
padding)→ 边框盒(border)→ 外边距盒(margin) - 内容盒:
width/height默认量这一层;内边距盒:背景铺到这里;外边距盒:盒子之间的透明间隔 outline和box-shadow画在外边距区之上,不占布局空间(不会把别的元素挤开)box-sizing: content-box(默认):width= 内容宽,padding/border往外加box-sizing: border-box(推荐):width= 内容 +padding+border,往内挤;内容盒最小为 0,不会负- 全局配方:
*, *::before, *::after { box-sizing: border-box; } box-sizingBaseline 广泛可用(2015 年 7 月起全浏览器支持),放心用margin可为负(拉近 / 重叠元素);padding不能为负- 逻辑属性:
padding-inline/margin-block等按书写方向(而非物理上下左右)取值,国际化更稳
一切皆盒:四个区域
CSS 把每个元素都渲染成一个矩形盒子,盒子从内到外分成四个区域(box),每个区域管一段距离:
┌─────────────── margin(外边距)────────────────┐
│ ┌──────────── border(边框)───────────────┐ │
│ │ ┌───────── padding(内边距)──────────┐ │ │
│ │ │ ┌────── content(内容)─────────┐ │ │ │
│ │ │ │ 文字 / 图片在这里 │ │ │ │
│ │ │ └───────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘- 内容盒(content box):内容真正所在的区域,内容本身能反过来撑大它(比如一段长文字会把盒子撑高)。
width/height默认量的就是这一层。 - 内边距盒(padding box):由
padding撑开,包在内容盒外。因为内边距在盒子内部,所以元素的背景会一直铺到这里——这是padding和margin最直观的区别。 - 边框盒(border box):由
border定义,是元素可见的框,包住内边距盒。 - 外边距盒(margin box):由
margin定义,是盒子周围、与其他盒子之间的透明间隔。outline(轮廓)和box-shadow(阴影)也画在这一区之上——它们只是画上去,不占据布局空间,不会把相邻元素推开。
box-sizing:width 到底量哪一层
同样写 width: 350px,盒子最终多宽,取决于 box-sizing。这是整个盒模型最容易踩、也最该先搞懂的一点。
content-box:默认,会「胀」
.box {
box-sizing: content-box; /* 默认值,可省略 */
width: 350px;
padding: 20px;
border: 10px solid;
}默认值 content-box 下,width / height 只管内容盒,内边距和边框是额外往外加的。上面这个盒子在屏幕上的实际宽度是:
350(内容) + 20×2(左右内边距) + 10×2(左右边框) = 410px也就是说,你写的 350px 不是盒子的最终宽度——一加内边距 / 边框,它就「胀」出去了。布局时要反复做这种加法,极易算错、溢出。
border-box:推荐,「所见即所得」
.box {
box-sizing: border-box;
width: 350px;
padding: 20px;
border: 10px solid;
}border-box 告诉 CSS:把 width 应用到边框盒。于是内边距和边框被往里挤,盒子的最终宽度铁定是你写的 350px,留给内容的宽度变成 350 − 20×2 − 10×2 = 290px。
一个安全保证
border-box 下内容盒的尺寸最小被钳到 0,不会变成负数。所以即使 padding + border 之和超过了 width,盒子也不会「消失」或塌成负宽——这让它在工程上比 content-box 可预测得多。
两者对比,一图记牢:
content-box(默认) | border-box(推荐) | |
|---|---|---|
width 量的是 | 内容盒 | 边框盒 |
padding / border | 往外加,盒子变大 | 往里挤,盒子不变 |
写 width: 350px 实际宽 | 350 + 内边距 + 边框 | 恰好 350 |
| 加内边距时 | 整体「胀」开,易溢出 | 外尺寸纹丝不动 |
全局 border-box 配方
正因为 border-box 让尺寸计算「所见即所得」,几乎所有现代项目都会在样式表最前面写上这一段,把它设为全局默认:
/* 所有元素 + 所有伪元素都用 border-box */
*,
*::before,
*::after {
box-sizing: border-box;
}MDN 对此的评价是:border-box 让「处理元素尺寸轻松得多,并消除了排版时一连串容易踩的坑」。这条规则今天已是事实标准。
别只设在 body 或个别元素上
box-sizing 不会继承(inherited: no)。只给 body 设 border-box,子元素仍是各自的默认 content-box。要全局生效,必须用 * 通配(或用「html 设 border-box + * { box-sizing: inherit }」的继承式写法)。
padding 与 margin 的关键差异
虽然都是「留白」,两者性质不同,混用是常见 bug 源头:
padding(内边距) | margin(外边距) | |
|---|---|---|
| 位置 | 边框内侧 | 边框外侧 |
| 背景 | 会铺到内边距区 | 透明,不显示背景 |
| 负值 | 不允许 | 允许(可拉近 / 重叠元素) |
| 合并 | 不合并 | 块级(垂直)方向会合并,详见下页 |
| 点击区域 | 算进元素(可点) | 不算(盒子之间的空隙) |
负 margin 是个有用但易混的特性——margin-top: -10px 会把元素往上提 10px,可用来制造重叠、抵消间距。它还牵扯外边距合并的计算,详见 外边距合并与 BFC。
逻辑属性:让内边距 / 外边距跟着书写方向走
物理属性 padding-left / margin-top 永远指向屏幕的左 / 上。但在阿拉伯语(从右到左)或竖排场景里,「行首」未必在左边。逻辑属性按书写方向取值,是国际化更稳的写法:
.card {
padding-inline: 1rem; /* 行向(左右排时 = 左右内边距) */
padding-block: 0.5rem; /* 块向(左右排时 = 上下内边距) */
margin-inline-start: auto; /* 行向起点(LTR 下 = 左) */
}*-inline:沿行方向(文字流动的方向),LTR 下对应左右;*-block:沿块方向(行堆叠的方向),横排下对应上下;*-inline-start/*-inline-end/*-block-start/*-block-end:四个方向的逻辑等价物。
逻辑属性与物理属性的对应关系会随 writing-mode / direction 改变——这正是它们的价值:一套代码自动适配多种书写方向。它们均为 Baseline 广泛可用。
小结
盒模型四层(内容 / 内边距 / 边框 / 外边距)是 CSS 布局的原子,而 box-sizing 决定 width 量哪一层——默认 content-box 会胀、推荐的 border-box 所见即所得,配上 * 全局重置是现代项目的第一条规则。盒子的大小定了,下一个问题是它在文档流里怎么参与排版——下一页讲 display 的内外显示类型:display 全谱。