跳转至

盒模型 — 每个元素都是四层盒子

这一章回答两类最常见的布局疑问: 「我明明写了 50% 宽,两个盒子怎么还挤不到一行」 「两个 20px 的外边距之间为什么只有 20px 的空」。 两个问题的答案都是盒模型:元素的实际占地,从来不止 width 一个数。

1. 这一章在全书链条里的位置

选择器(02)解决选谁,层叠(03)解决谁生效。这一章讲「生效之后,元素到底占多大地方」—— 这是布局的地基,第 05 章(display、定位)、第 06/07 章(Flex、Grid)全建在它的概念上。 不理解盒模型,后面所有「对齐」「间距」「居中」的讲解都会悬空。

2. 顶层全景:四层盒子剖面

        ┌─────────────── margin ────────────────┐
        │  ┌──────────── border ────────────┐   │
        │  │  ┌──────── padding ─────────┐  │   │
        │  │  │                          │  │   │
        │  │  │        content           │  │   │
        │  │  │     (文字、图片)        │  │   │
        │  │  │                          │  │   │
        │  │  └──────────────────────────┘  │   │
        │  └────────────────────────────────┘   │
        └───────────────────────────────────────┘

图说:margin 推别人,border 画线,padding 撑自己,content 装内容。
背景色铺到 padding 为止,铺不进 margin。

书里那句话是本章的地基:「CSS 里每个 HTML 元素都被视为一个矩形盒子」, 布局的全部计算都在这个盒子上发生1。四层各自的职责:

层 位置 干什么
content 最里 装文字和图片
padding 内容外、边框内 内容和边框之间的留白
border padding 外 绕盒子一圈的线
margin 最外 把这个盒子和其他盒子推开

顺带一个马上要用的事实:背景色和背景图会铺到 padding,但在 margin 处戛然而止2—— 「卡片底色和边框之间有留白」的效果,就是 padding 在起作用。

3. 核心原理:宽度到底怎么算

主线例子:一个 200px 的盒子,实际多宽

输入:

.modern-box {
  box-sizing: border-box;   /* 先押后讲,先看不带它的版本 */
  width: 200px;
  padding: 20px;
  border: 5px solid black;
}

默认算法(content-box):width: 200px 只管内容层。 内边距(左右各 20)和边框(左右各 5)在 200 之外另加: 实际占地 = 200 + 20 + 20 + 5 + 5 = 250px3。 这就是书里叫「计算缺口」(The Calculation Gap) 的坑:补了内边距和边框, 元素就比声明的宽度更宽4。

这个缺口在「百分比布局」上最毒:两个盒子各写 width: 50%,再各加一点 padding, 加起来就超过 100%,第二个盒子被挤到下一行——书里把它列为布局「破碎」的第一大原因5。

border-box 算法:box-sizing: border-box 把 width 的定义改成 「含内容 + 内边距 + 边框的总宽」。同样这行 200px,内容层自动收缩成 200 − 20 − 20 − 5 − 5 = 150px,总宽死死咬住 200px6。

声明 width: 200px + padding 20px + border 5px

content-box(默认)   │████ 内容 200px ████│20│5│   总宽 250px
border-box          │██ 内容 150px ██│20│5│        总宽 200px

图说:border-box 让「宽度」重新等于直觉里的宽度。数字与原书示例一致。

一条起手式统治所有现代项目

把 border-box 施加给一切元素,是行业事实标准:

* {
  box-sizing: border-box;
  margin: 0;
}

通配选择器 * 选中每个元素(第 02 章),一行解决全站。 margin: 0 顺手把浏览器自带的默认外边距清掉——h1、p 们「自带的空白」就是它们。

简写:四个值按顺时针背

padding: 5px 10px 15px 20px; 四个值按上、右、下、左(顺时针)分配; 省略有固定规则:

写法 实际意思
padding: 20px; 四边都是 20
padding: 10px 20px; 上下 10,左右 20
padding: 5px 10px 15px; 上 5,左右 10,下 15
padding: 5px 10px 15px 20px; 上 5、右 10、下 15、左 20

margin 同一条规则。记不住的背法:从上开始顺时针,缺的与对边相同。

外边距折叠:两个 20 不等于 40

这是盒模型里最反直觉的一条。两个上下相邻的元素:

.box1 { margin-bottom: 20px; }
.box2 { margin-top: 20px; }

直觉上它们之间该有 40px 空隙。实际只有 20px:浏览器把两个垂直外边距 「折叠」成一个,取较大的那个7。左右方向不折叠;Flex/Grid 容器里的子项之间也不折叠。 修法规整:与其记折叠的触发条件,不如改用 gap(第 06 章)—— display: flex; flex-direction: column; gap: 20px; 写 20 就得 20,永不折叠。

居中一行:margin: 0 auto

margin 有个特殊值 auto:水平方向设成 auto,浏览器把剩余宽度平分两边。 所以「块级元素水平居中」的标准答案永远是:

.centered-container {
  width: 80%;
  margin: 0 auto;   /* 上下 0,左右自动 → 居中 */
}

0 是上下,auto 是左右——这两口子各管一个方向8。

4. 作者的判断与证据

  • 「忘加 border-box 是布局破碎的第一大原因」——全书少数带排行的断言, 经验性,无数据,但与业界共识一致5。
  • 「margin 折叠:取较大者;左右不折叠」——事实性陈述,书里只给了结论 没给触发条件的完整清单(折叠还发生在父子之间、空元素上,本书未展开)。
  • 「inline 元素上加垂直 padding 会压到上下行,改 inline-block 解决」—— 经验断言,指向第 05 章的 display9。

5. 边界与局限

  • margin 折叠只讲了「相邻兄弟」一种触发情形;父子的折叠(子元素的 margin 穿透父元素) 也是日常撞墙高发区,本书未提,读者撞上时请查 MDN「margin collapsing」词条。
  • 没讲 outline(描边,不占空间)与 border 的区别,也没讲盒子的 min-width/max-width (第 12 章的响应式会用到 max-width)。
  • box-sizing 的第三种取值(inherit)未提,无关紧要。

判断(我们的,不是书里的): 「先讲默认行为、再讲 border-box 修正」是本书讲法的优点—— 很多教程一上来就 * { box-sizing: border-box },读者不知道自己在规避什么。 本书让缺口(250px)先暴露在眼前,再给出修正,因果完整。 如果错,会错在: 对完全的新手,「为什么默认是这么个坑」的答案(历史兼容性) 本书同样没讲——只给了「现状 + 修正」,好奇心强的读者仍会欠一个答案。

6. 可带走的

  1. 四层:content / padding / border / margin;背景铺到 padding 为止12。
  2. 默认(content-box)下 width 只管内容:200 + 20 + 20 + 5 + 5 = 250px3。
  3. box-sizing: border-box 让 width = 总宽,写多少占多少6。
  4. 起手式 * { box-sizing: border-box; margin: 0; },所有现代项目的默认开头5。
  5. 四值简写顺时针:上、右、下、左;缺则对边相同。
  6. 垂直外边距折叠:两个 20 之间是 20 不是 40;要稳就用 flex + gap7。
  7. 块级元素水平居中:width + margin: 0 auto8。

7. 原文地图

主题 原书章 原文位置
每个元素都是矩形盒子 Chapter 4: Box Model Reference text/05-ch01-1-chapter-overview.txt:7(搜「rectangular box」)
四层职责 同上 text/05-ch01-1-chapter-overview.txt:19(搜「Content Area」)
计算缺口 同上 text/05-ch01-1-chapter-overview.txt:27(搜「Calculation Gap」)
content-box vs border-box 同上 text/05-ch01-1-chapter-overview.txt:110(搜「Padding and borders are added」)
250px 的完整算式 同上 text/05-ch01-1-chapter-overview.txt:123(搜「250px」)
忘 border-box 是第一大坑 同上 text/05-ch01-1-chapter-overview.txt:149(搜「#1 cause」)
外边距折叠 同上 text/05-ch01-1-chapter-overview.txt:151(搜「collapse」)
inline 元素的垂直 padding 同上 text/05-ch01-1-chapter-overview.txt:153(搜「Inline Elements」)
背景铺到 padding 同上 text/05-ch01-1-chapter-overview.txt:155(搜「extend under the padding」)
margin: 0 auto 居中 同上 text/05-ch01-1-chapter-overview.txt:127(搜「Centering a Block」)
卡片组件组合 同上 text/05-ch01-1-chapter-overview.txt:135(搜「Card Component」)
padding 简写 同上 text/05-ch01-1-chapter-overview.txt:52(搜「Shorthand」)

  1. 出处:「Chapter 4: Box Model Reference」(text/05-ch01-1-chapter-overview.txt:7,搜「rectangular box」)。原文:「In CSS, every single HTML element is considered a rectangular box. The Box Model is the foundation of design and layout.」 ↩↩

  2. 出处:「Chapter 4: Box Model Reference」(text/05-ch01-1-chapter-overview.txt:155,搜「extend under the padding」)。原文:「Remember that background colors and images extend under the padding, but stop at the margin.」 ↩↩

  3. 出处:「Chapter 4: Box Model Reference」(text/05-ch01-1-chapter-overview.txt:123,搜「250px」)。原文:「If this were content-box, the total width would be 250px (200 + 20+20 padding + 5+5 border).」 ↩↩

  4. 出处:「Chapter 4: Box Model Reference」(text/05-ch01-1-chapter-overview.txt:27,搜「Calculation Gap」)。原文:「By default, adding padding and borders makes an element wider than its defined width.」 ↩

  5. 出处:「Chapter 4: Box Model Reference」(text/05-ch01-1-chapter-overview.txt:149,搜「#1 cause」)。原文:「This is the #1 cause of layouts "breaking" (e.g., two 50% width boxes not fitting side-by-side because of padding). Use the Universal Selector to apply border-box to everything.」 ↩↩↩

  6. 出处:「Chapter 4: Box Model Reference」(text/05-ch01-1-chapter-overview.txt:110,搜「Padding and borders are added」;:123 搜「remains exactly 200px」)。原文:border-box 下「the total width remains exactly 200px」。 ↩↩

  7. 出处:「Chapter 4: Box Model Reference」(text/05-ch01-1-chapter-overview.txt:151,搜「collapse」)。原文:「Top and bottom margins of adjacent elements sometimes 'collapse' into a single margin equal to the largest of the two. This does not happen for left/right margins.」 ↩↩

  8. 出处:「Chapter 4: Box Model Reference」(text/05-ch01-1-chapter-overview.txt:127,搜「Centering a Block」)。原文:「To center a div or another block element horizontally, set the width and set horizontal margins to auto.」 ↩↩

  9. 出处:「Chapter 4: Box Model Reference」(text/05-ch01-1-chapter-overview.txt:153,搜「Inline Elements」)。原文:「Vertical padding on inline elements (like ) may overlap other lines of text. Use display: inline-block to fix this.」 ↩