Skip to content

盒模型与 box-sizing

基于 CSS 现代标准 · 核于 2026-06

速查

  • 四层(由内向外):内容盒内边距盒padding)→ 边框盒border)→ 外边距盒margin
  • 内容盒:width / height 默认量这一层;内边距盒:背景铺到这里;外边距盒:盒子之间的透明间隔
  • outlinebox-shadow 画在外边距区之上,不占布局空间(不会把别的元素挤开)
  • box-sizing: content-box默认):width = 内容宽,padding / border 往外
  • box-sizing: border-box推荐):width = 内容 + padding + border,往内;内容盒最小为 0,不会负
  • 全局配方:*, *::before, *::after { box-sizing: border-box; }
  • box-sizing Baseline 广泛可用(2015 年 7 月起全浏览器支持),放心用
  • margin 可为负(拉近 / 重叠元素);padding 不能为负
  • 逻辑属性:padding-inline / margin-block 等按书写方向(而非物理上下左右)取值,国际化更稳

一切皆盒:四个区域

CSS 把每个元素都渲染成一个矩形盒子,盒子从内到外分成四个区域(box),每个区域管一段距离:

┌─────────────── margin(外边距)────────────────┐
│  ┌──────────── border(边框)───────────────┐  │
│  │  ┌───────── padding(内边距)──────────┐  │  │
│  │  │  ┌────── content(内容)─────────┐  │  │  │
│  │  │  │      文字 / 图片在这里         │  │  │  │
│  │  │  └───────────────────────────────┘  │  │  │
│  │  └─────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────┘  │
└──────────────────────────────────────────────────┘
  • 内容盒(content box):内容真正所在的区域,内容本身能反过来撑大它(比如一段长文字会把盒子撑高)。width / height 默认量的就是这一层。
  • 内边距盒(padding box):由 padding 撑开,包在内容盒外。因为内边距在盒子内部,所以元素的背景会一直铺到这里——这是 paddingmargin 最直观的区别。
  • 边框盒(border box):由 border 定义,是元素可见的框,包住内边距盒。
  • 外边距盒(margin box):由 margin 定义,是盒子周围、与其他盒子之间的透明间隔。outline(轮廓)和 box-shadow(阴影)也画在这一区之上——它们只是画上去,不占据布局空间,不会把相邻元素推开。

box-sizingwidth 到底量哪一层

同样写 width: 350px,盒子最终多宽,取决于 box-sizing。这是整个盒模型最容易踩、也最该先搞懂的一点。

content-box:默认,会「胀」

css
.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:推荐,「所见即所得」

css
.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 让尺寸计算「所见即所得」,几乎所有现代项目都会在样式表最前面写上这一段,把它设为全局默认:

css
/* 所有元素 + 所有伪元素都用 border-box */
*,
*::before,
*::after {
  box-sizing: border-box;
}

MDN 对此的评价是:border-box 让「处理元素尺寸轻松得多,并消除了排版时一连串容易踩的坑」。这条规则今天已是事实标准。

别只设在 body 或个别元素上

box-sizing 不会继承inherited: no)。只给 bodyborder-box,子元素仍是各自的默认 content-box。要全局生效,必须用 * 通配(或用「htmlborder-box + * { box-sizing: inherit }」的继承式写法)。

paddingmargin 的关键差异

虽然都是「留白」,两者性质不同,混用是常见 bug 源头:

padding(内边距)margin(外边距)
位置边框边框
背景会铺到内边距区透明,不显示背景
负值不允许允许(可拉近 / 重叠元素)
合并不合并块级(垂直)方向会合并,详见下页
点击区域算进元素(可点)不算(盒子之间的空隙)

margin 是个有用但易混的特性——margin-top: -10px 会把元素往上提 10px,可用来制造重叠、抵消间距。它还牵扯外边距合并的计算,详见 外边距合并与 BFC

逻辑属性:让内边距 / 外边距跟着书写方向走

物理属性 padding-left / margin-top 永远指向屏幕的左 / 上。但在阿拉伯语(从右到左)或竖排场景里,「行首」未必在左边。逻辑属性按书写方向取值,是国际化更稳的写法:

css
.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 全谱