CSS 盒模型

盒模型是 CSS 布局的地基。页面上的每一个元素都是一个矩形盒子,从内到外由四层组成。理解了盒子怎么算尺寸、怎么相互影响,你才能精准控制元素的占地大小和间距。这一篇是后面所有布局章节的前置知识。

1. 盒子的四层结构

从里到外,每个盒子由这四层组成(像套娃一样):

.box {
  width: 200px;          /* 内容区宽度 */
  height: 100px;         /* 内容区高度 */
  padding: 20px;         /* 内边距:内容到边框的距离 */
  border: 2px solid #333;/* 边框 */
  margin: 16px;          /* 外边距:边框到相邻元素的距离 */
  box-sizing: border-box;/* 让 width 包含 padding 和 border */
}

记住一个类比:padding 是"盒子里的填充物"(在内部),margin 是"两个盒子之间的空隙"(在外部)。新手最容易搞反这俩——记住"padding 在内、margin 在外"。

2. box-sizing:最关键的属性

这是盒模型里最重要的概念,也是新手最容易踩的坑。默认情况下,你设的 width 只算内容区——加上 padding 和 border 后,盒子实际占的宽度会比设的大。

/* 默认 content-box:width 只算内容区 */
/* 实际占用宽度 = 200 + 20*2 + 2*2 = 244px */
.box-a {
  width: 200px;
  padding: 20px;
  border: 2px solid #333;
  box-sizing: content-box;   /* 浏览器默认值 */
}

/* border-box:width 包含 padding 和 border */
/* 实际占用宽度 = 200px(内容区自动缩到 156px) */
.box-b {
  width: 200px;
  padding: 20px;
  border: 2px solid #333;
  box-sizing: border-box;
}

/* 全局推荐:所有元素都改用 border-box */
* {
  box-sizing: border-box;
}

看例子:同一个 width: 200px,content-box 下实际占 244px,而 border-box 下实际就 200px。后者把 padding 和 border 算进了 width,算尺寸直观得多。

实际项目几乎都会全局开 border-box,写在 reset 里:

这是前端工程的"默认规矩",几乎所有现代框架(Bootstrap、Tailwind)都这么做。从今天起,你的每个项目都应该开头加这一行。

3. padding 简写

padding 和 margin 的简写规则完全一样,掌握一个就会另一个。规则是从 12 点方向开始顺时针:上、右、下、左。

.box {
  /* 四个方向各设 */
  padding-top: 10px;
  padding-right: 20px;
  padding-bottom: 10px;
  padding-left: 20px;

  /* 简写:上 右 下 左(从 12 点方向顺时针) */
  padding: 10px 20px 10px 20px;

  /* 两个值:上下 左右 */
  padding: 10px 20px;

  /* 一个值:四个方向全相同 */
  padding: 10px;
}

简写省略规则:写一个值=四个方向都一样;写两个值=上下、左右;写三个值=上、左右、下;写四个值=上、右、下、左。这和时钟方向一致,记住了就再也不会写反。

4. margin 简写与水平居中

margin 简写和 padding 完全一致,但有一个 padding 做不到的常用技巧:水平居中

.box {
  /* 简写规则和 padding 完全一致 */
  margin: 10px 20px;     /* 上下 10,左右 20 */

  /* 居中一个有固定宽度的块级元素 */
  width: 600px;
  margin: 0 auto;        /* 上下 0,左右 auto = 自动平分 = 水平居中 */

  /* 负 margin:让元素超出父级或重叠(慎用) */
  margin-top: -10px;
}

margin: 0 auto 是把左右都设成 auto,浏览器会自动平分剩余空间,从而让块级元素在父容器里水平居中。前提是元素必须有明确的 width(没有宽度,auto 就没剩余空间可分了)。

注意:margin 可以是负值,让元素超出父级或与相邻元素重叠。padding 不能是负值。

5. margin 合并(塌陷)— 必踩的坑

这是新手最常遇到的"诡异现象":两个上下相邻的块级元素,它们的上下 margin不会相加,而是取较大者。比如 A 的下边距是 30px,B 的上边距是 20px,实际间距只有 30px,不是 50px。

<!-- 上下相邻块级元素的 margin 会"合并"取较大值 -->
<style>
  .a { margin-bottom: 30px; }
  .b { margin-top: 20px; }
  /* 两个段落之间的实际间距是 30px,不是 50px */
</style>

<p class="a">第一段</p>
<p class="b">第二段</p>

<!-- 解决方法 1:改成 padding -->
<!-- 解决方法 2:给父元素加 overflow: hidden 或 padding -->
<!-- 解决方法 3:用 Flex/Grid(它们不会发生 margin 合并) -->

这只发生在块级元素的上下方向(左右不合并,父子的上下也会合并)。解决办法有几个:

6. display 类型

每个元素都有一个 display 属性,决定它怎么"摆"在页面上。常见取值:

/* block:独占一行,可设宽高 */
div, p, h1, ul, li { display: block; }

/* inline:不换行,宽高无效(只占内容那么大) */
span, a, strong, em { display: inline; }

/* inline-block:不换行,但可以设宽高(最佳折中) */
.btn { display: inline-block; padding: 8px 16px; }

/* none:完全隐藏,不占空间 */
.modal { display: none; }

/* flex / grid:把元素变成弹性/网格容器 */
.toolbar { display: flex; }
.gallery { display: grid; }

注意:行内元素(inline)设宽高、上下 margin/padding 都无效或表现异常——想给 <a><span> 设尺寸,把它改成 inline-blockflex 即可。

小结

盒模型是布局的原子:content 是内容、padding 是内部留白、border 是边框、margin 是外部空隙;全局开 box-sizing: border-box 让尺寸直观;上下 margin 会合并,改用 padding 或 Flex 解决;display 决定元素怎么摆。下一篇讲文本与字体——让文字真正好看起来的那些属性。

← 上一篇 CSS 选择器

下一篇 CSS 文本与字体

✈️💬