05盒模型

浏览器眼里,每个元素都是一个矩形盒子:内容、内边距、边框、外边距四层套娃。 弄懂盒模型,就弄懂了 CSS 布局的一半——为什么 div 设了 width 却「越量越宽」、 为什么两个盒子之间会「神秘合并」,答案全在盒子里。

约 18 分钟 8 个动手实验 布局第一课

一、万物皆盒:四层解剖图

从里到外四层:content(内容)→ padding(内边距)→ border(边框)→ margin(外边距)。 padding 是「盒子里面的软垫」,撑大盒子本体的透明区域; margin 是「盒子外面的气场」,负责推开别人,永远透明。

margin 外边距 · 永远透明,只负责推开别人
border 边框 · 盒子的实体边
padding 内边距 · 有背景色的软垫
content 内容区
width / height 默认量这里
背景色会铺满 content + padding 直到 border 内沿;margin 永远是透明的「社交距离」
四层速查:谁能染色、谁占尺寸
层级名字能设颜色吗占尺寸吗一句话
第 1 层content—(背景透出)真正放文字图片的地方
第 2 层padding✓(跟背景色)内容与边框之间的软垫
第 3 层border盒子的实体边
第 4 层margin✗ 永远透明✗(只推开别人)盒子间的社交距离

把四层同时开到一个元素上,看它们各自的「势力范围」:

四层套娃实体图:分别把 paddingbordermargin 改大,看哪几层跟着变胖
记法:padding 是「私人物品」(撑大自己、有背景色)、 margin 是「社交距离」(推开别人、永远透明)。点 F12 → Elements → 右下角 Styles 旁的彩色盒模型图,四层一秒看懂。

二、width 到底量到哪:content-box vs border-box

这是盒模型最重要的一课。默认 box-sizing: content-box 下, width 只量内容区——加上 padding 和 border 后,盒子实际宽度 = width + padding×2 + border×2。border-box 则让 width「一口价包含全部」。

box-sizing 两个值:width 这把尺子量到哪
效果使用场景
content-box(默认值)width 只量内容区,padding / border 额外加上去兼容老代码;需要精确控制「内容净尺寸」时
border-boxwidth 一口价:内容 + padding + border 全包现代项目标配,重置样式里全站开启
同样 width:160px,两种盒子的真实宽度:把 .cb 的 border 改成 20px,左边继续长胖、右边纹丝不动
为什么全世界的重置样式都有 * { box-sizing: border-box }? 因为算加法(content-box)反人类——设计稿量出来 200px,你就写 200px, padding、border 都从里面扣,不用再拿计算器。

三、padding:盒内软垫的四种写法

和 margin 语法完全一致:1~4 个值按上 → 右 → 下 → 左顺时针转一圈, 缺的值「对面补齐」。

padding / margin 简写规则:一到四个值,顺时针 + 对面补齐
写法展开含义记忆
padding: 8px上 8、右 8、下 8、左 8一个值管四面
padding: 8px 24px上下 8,左右 24先上下、后左右
padding: 4px 8px 28px上 4,左右 8,下 28缺的「左」找对面的「右」补齐
padding: 4px 8px 6px 12px上 4、右 8、下 6、左 12顺时针转一整圈
padding-left: 20px只设一面微调时用单边属性
margin: 0 auto上下 0,左右自动平分(仅 margin 有 auto)块级水平居中,第五节细讲
金色区域就是 padding:把 .pd-c 的第 3 个值改成 40px,看底部软垫变厚
按钮变大法:给按钮加 padding: 12px 32px,比写死 width/height 更灵活—— 文字多长按钮就多长,中英文都适用。

四、margin:外边距与著名的「合并」现象

margin 推开相邻元素。但有个垂直方向的经典陷阱: 上下两个块级元素的 margin-bottom 和 margin-top 不会叠加,取大的那个—— 这叫「外边距合并」。左右方向没有这个现象。

合并现场:间距取 max(40, 60) = 60 而非相加。把 margin-top 改成 20px——间距不变,因为 40 更大
外边距合并三种情形与规避:谁合并、谁不合并
情形合并结果规避办法
相邻兄弟:A 的 margin-bottom 遇上 B 的 margin-top 取两者较大值,不相加 团队约定统一只写 margin-bottom,最省心
父子首尾:父元素与第一个 / 最后一个孩子的上 / 下 margin 合并取大,看起来像「父被孩子的 margin 顶跑」 父元素加 padding / border 挡住,或加 overflow: hidden 触发 BFC
空块自身:没有内容、没有 padding / border 的空元素 它自己的 margin-top 和 margin-bottom 也会合并取大 别用空 div 撑间距,改用 padding 或固定高度
不合并的:左右方向、行内元素、flex / grid 项目 正常相加
防合并三板斧:父元素加 overflow: hidden(触发 BFC)、 父元素加 padding/border 挡住、或干脆「间距只写在一侧」—— 实战中团队约定统一只用 margin-bottom 最省心。

五、margin auto:块级盒子水平居中

给有宽度的块级元素写 margin: 0 auto,左右 auto 会平分剩余空间, 盒子就居中了。注意两个前提:盒子必须有 width、必须是块级元素。

水平居中:把 width 那行删掉,盒子立刻铺满失去居中——前提一不成立
margin: 0 auto 只能水平居中;垂直居中它无能为力 (垂直方向的 auto 算出来是 0)。想上下也居中,要用 flex——布局模块见。

六、border:三件套 width / style / color

border 必须三个属性齐活才显示,其中style 是灵魂—— 不写 style,width 写 100px 也是白搭。(上一章已逐个属性细讲,这里看它们在盒子上的表现。)

六种边框写法:把 .bd-oneborder-bottom 改成 border-top,看分隔线跑到上面
四条边可以单独控制:border-top / right / bottom / left 各自的三件套随便组合。 透明边框 border: 1px solid transparent 还能用来「占位防抖动」。

七、outline:不占空间的描边

outline 长得像 border,但不占布局空间: 加 10px 的 outline,盒子纹丝不动;加 10px 的 border,盒子立刻被撑大。 它最著名的舞台是键盘聚焦时的焦点圈

右边盒子描了 3px 外圈,宽高纹丝不动:把 outline-offset 改成 8px,看空隙变大
千万别为了好看写 outline: none 又不给替代样式—— 键盘用户将完全迷失在你的页面里。要么留着,要么换成明显的自定义焦点样式。

八、在 DevTools 里「看见」盒模型

F12 → Elements → 选中元素 → 右下角 Styles 面板下方,有一张彩色盒模型图: 橙黄=margin、绿黄=border、绿=padding、蓝=content,鼠标悬停对应区域, 页面上的盒子会同步高亮。调间距时改这里的数字,所见即所得。

模拟 DevTools 盒模型视图:把 .dt-mid 的 border 改成 12px,看金色边框层变厚
现在就试:在本页按 F12,点左上角箭头再点任意卡片, 右下角盒模型图会显示它的 padding/margin 实时数值——这是之后调布局的日常操作。

九、本章小结

  • 四层套娃:content → padding(有背景、占位)→ border → margin(透明、推开别人)。
  • box-sizing: border-box 让 width 一口价;项目开头必写 * { box-sizing: border-box }
  • padding/margin 一到四个值顺时针展开:上右下左,缺的找对面补齐。
  • 垂直 margin 相邻会合并取大值;防合并用 BFC、挡板或统一单侧。
  • margin: 0 auto 水平居中的前提:块级 + 有 width。
  • border 三件套 width/style/color,style 不写全白搭;单边 border 是分隔线神器。
  • outline 不占空间,是焦点圈专用;去掉焦点圈必须给替代方案。
  • DevTools 盒模型图是调间距的「透视眼」,四色分区所见即所得。
动手练习:做三张「名片」——同一份 HTML,第一张 content-box、第二张 border-box (同样 width:220px 对比实际宽度)、第三张 border-box + padding:20px + border:5px, 全部 margin: 0 auto 居中,中间用 margin-bottom 控制间距。 再 F12 打开盒模型图验证你算的数字。