大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
盒模型
这一课你将能做到
- 画出盒模型四层结构:content、padding、border、margin
- 说清楚 content-box 和 border-box 的区别
- 解释 margin 折叠现象并能规避
- 在 F12 DevTools 里查看任何元素的盒模型
为什么要学
盒模型是 CSS 布局的根基。每个元素都是一个矩形盒子,width、padding、border、margin 加起来才是它的真实占地面积。不理解盒模型,你就不知道为什么 width: 100% 加 padding 会撑破容器,为什么两个 margin 会合并。
人话:盒模型像快递包裹——物品本身是 content,泡沫填充是 padding,纸箱是 border,包裹之间的间隔是 margin。
先建立图像
┌────────────────────────── margin ──────────────────────────┐
│ ┌────────────────────── border ──────────────────────┐ │
│ │ ┌────────────────── padding ──────────────────┐ │ │
│ │ │ ┌──────────── content ────────────┐ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ 实际内容(文字、图片) │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ └─────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
实际占用宽度 = margin×2 + border×2 + padding×2 + width
跟着做
步骤 1:四层结构
.box {
width: 200px; /* content 宽 */
padding: 20px; /* 内边距 */
border: 5px solid #333; /* 边框 */
margin: 30px; /* 外边距 */
background: #ffe4e1;
}
content-box(默认)下:实际宽 = 200 + 20×2 + 5×2 = 250px,再加 margin 30×2,对外占地 310px。
步骤 2:padding 内边距
.box { padding: 20px; } /* 四边都 20 */
.box { padding: 10px 20px; } /* 上下 10,左右 20 */
.box { padding: 10px 20px 30px; } /* 上 10,左右 20,下 30 */
.box { padding: 10px 20px 30px 40px; } /* 上右下左(顺时针) */
/* 单独一边 */
.box { padding-top: 10px; }
padding 是内容和边框之间的填充,会带着背景色。
步骤 3:border 边框
.box { border: 2px solid #333; } /* 宽度 样式 颜色 */
.box { border: 1px dashed red; }
.box { border-radius: 8px; } /* 圆角 */
.box { border-radius: 50%; } /* 圆形(需正方形) */
/* 单独一边 */
.box { border-bottom: 1px solid #eee; } /* 卡片分割线常用 */
边框样式:solid dashed dotted double none。
步骤 4:margin 外边距
.box { margin: 20px; } /* 四边 */
.box { margin: 0 auto; } /* 上下 0,左右自动 = 水平居中 */
.box { margin-top: -10px; } /* 负 margin,往上拽 */
margin 是元素之间的间隔,透明、不显示背景。
步骤 5:box-sizing——重点
/* 默认行为,width 只是 content 宽 */
.default { box-sizing: content-box; width: 200px; padding: 20px; }
/* 实际宽 = 200 + 40 = 240 */
/* 推荐:width 包含 content + padding + border */
.modern { box-sizing: border-box; width: 200px; padding: 20px; }
/* 实际宽就是 200,content 自动被压成 160 */
工程实践,全局设置:
*, *::before, *::after {
box-sizing: border-box;
}
为什么?直觉上 width: 200px 就应该是「这个盒子 200 宽」,而不是「content 200 加 padding 又变成 240」。
步骤 6:margin 折叠
相邻块级元素的垂直 margin 会合并,取较大值:
<style>
.a { margin-bottom: 30px; }
.b { margin-top: 20px; }
</style>
<div class="a">A</div>
<div class="b">B</div>
A 和 B 之间不是 50px,而是 30px(取大值)。
父元素和第一个子元素的 margin-top 也会折叠:子的 margin-top 会「穿透」到父元素外面。
规避方法(任选其一):
- 给父元素加
padding-top: 1px或border-top: 1px solid transparent - 给父元素
overflow: hidden(创建 BFC) - 改用
padding而不是margin - 用 Flex/Grid 布局(flex/grid 容器里 margin 不折叠)
步骤 7:F12 查看盒模型
打开 DevTools → Elements → 选中元素 → 右侧 Computed → 拉到最底部,看到一个彩色矩形图:
- 中间白/浅色 = content
- 内圈 = padding
- 边框色 = border
- 最外橙黄 = margin
鼠标悬停页面元素,会直接看到这四层的高亮。
讲清楚要点
- margin 是「我和别人之间」,padding 是「我内部」:要留白但保留背景色用 padding,纯间隔用 margin。
- box-sizing: border-box 是现代默认:所有 UI 框架都这么做。
- margin 折叠只发生在垂直方向:左右 margin 永远不折叠。
- 行内元素的 margin/padding 上下不生效:
span设padding-top不影响布局,要改成inline-block或block。 - margin 可以用 auto:
margin: 0 auto水平居中块级元素(前提:元素有宽度)。
你可能会懵的地方
-
为什么我设了
width: 100%还溢出? content-box 下,padding 和 border 加在 100% 之外。改border-box即可。 -
margin 折叠是 Bug 吗? 不是,是规范。最初为了让段落间距更优雅,避免上下两个 margin 简单相加。
-
margin: auto 为什么能居中? auto 会均分剩余空间。
margin: 0 auto上下 0 左右均分,所以水平居中。margin: auto在 flex 容器里能垂直也居中。 -
padding 能用百分比吗? 能,但百分比是相对父元素宽度(不是高度!)。所以
padding-top: 56.25%可以做出 16:9 自适应盒子。 -
行内元素 padding 真的没用吗? 上下 padding 会影响背景色渲染但不推挤邻居;左右 padding 正常生效。要让上下 padding 推挤布局,改
display: inline-block。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
width: 100%; padding: 20px; | content-box 溢出父容器 | 加 box-sizing: border-box |
用多个 <br> 做间距 | 滥用换行 | 用 margin/padding |
margin: 0 auto 但没设 width | 块级元素默认 100%,无法居中 | 加 width: 600px 或 max-width |
想垂直居中用 margin: auto 0 | 普通块级上下文垂直 auto = 0 | 用 flex 或绝对定位 |
给 span 设 padding-top 期望推开邻居 | 行内元素上下 padding 不影响布局 | 改 display: inline-block |
卡点急救
- 盒子宽度算不对:F12 → Computed → Box Model 图,四层数值一目了然。
- 元素间多出神秘间距:检查是否是 margin 折叠;或行内块之间的空白字符。
- 内容贴边难看:加
padding;改完发现元素变大?加box-sizing: border-box。
面试常问
-
盒模型两种模式区别? content-box:width 只包含内容;border-box:width 包含 content + padding + border。IE 老版本默认 border-box,W3C 标准默认 content-box。
-
margin 折叠的规则? 只在垂直方向、块级上下文、相邻或父子无分隔时发生;取较大值(同号)或相加(异号);BFC、flex、grid 容器内不折叠。
-
怎么让 div 水平居中?
width: xxx; margin: 0 auto;或父元素display: flex; justify-content: center;或父元素text-align: center(仅对行内/行内块子元素有效)。
自测三问
width: 200px; padding: 20px; border: 5px solid;在 content-box 和 border-box 下实际宽各是多少?- 父元素和第一个子元素的 margin-top 折叠怎么规避?
- 为什么
padding-top: 50%是相对父元素宽度而不是高度?
小结一句话
盒模型是布局的原子——content 是肉、padding 是衣、border 是皮、margin 是社交距离;box-sizing: border-box 一设,世界清净。
延伸
- MDN 盒模型
- 下一课:display,理解块级与行内的本质差异。