盒模型 — 每个元素都是四层盒子
盒模型 — 每个元素都是四层盒子
这一章回答两类最常见的布局疑问: 「我明明写了 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. 可带走的
- 四层:content / padding / border / margin;背景铺到 padding 为止12。
- 默认(content-box)下 width 只管内容:200 + 20 + 20 + 5 + 5 = 250px3。
box-sizing: border-box让 width = 总宽,写多少占多少6。- 起手式
* { box-sizing: border-box; margin: 0; },所有现代项目的默认开头5。 - 四值简写顺时针:上、右、下、左;缺则对边相同。
- 垂直外边距折叠:两个 20 之间是 20 不是 40;要稳就用 flex + gap7。
- 块级元素水平居中:
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」) |
Footnotes
-
出处:「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.」 ↩ ↩2 -
出处:「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).」 ↩ ↩2 -
出处:「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.」 ↩ -
出处:「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.」 ↩ ↩2 ↩3 -
出处:「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」。 ↩ ↩2 -
出处:「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.」 ↩ ↩2 -
出处:「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.」 ↩ ↩2 -
出处:「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.」 ↩