CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
HTML 与 CSS 基础/课时/盒模型与布局流
RawBlame
课时目录12 节

HTML 与 CSS 基础

  1. 01网页如何工作
  2. 02HTML 文档结构
  3. 03文本、链接与媒体
  4. 04HTML 表单
  5. 05语义化与可访问性
  6. 06CSS 选择器与层叠
  7. 07盒模型与布局流
  8. 08Flexbox 布局
  9. 09Grid 布局
  10. 10响应式设计
  11. 11综合练习:静态课程页
  12. 12框架与下一步

盒模型与布局流

margin/padding/border、display、position。

30 分钟

CSS 盒模型

这一课你将能做到

  1. 准确说出盒模型四个区域(content、padding、border、margin)的职责和计算方式
  2. 理解 box-sizing: border-box 与默认 content-box 的区别,并知道为什么现代开发统一使用 border-box
  3. 使用 outline、box-shadow、margin-collapse 等周边机制,避免常见的布局偏差

为什么要学

盒模型是 CSS 布局的「原子理论」。浏览器把页面上每个元素都当作一个矩形盒子,无论它是文字、图片还是按钮。你设置的 width: 300px 到底包含不包含内边距?两个盒子上下相邻时,间距为什么不是两者之和而是取较大值?这些看似琐碎的细节,决定了 CodeForge 的课程卡片为什么在 Chrome 和 Firefox 中宽度不一致,也决定了你能否精确还原设计稿。

不理解盒模型,你就无法解释「为什么 width: 100% 加了 padding: 20px 就超出容器」,也无法诊断「为什么两个元素之间多了 10px 空白」。这些问题在面试中几乎必问,在实际工作中天天遇到。

先建立图像

一个标准的盒模型结构:

+--------------------------- margin ---------------------------+
|  +----------------------- border ------------------------+  |
|  |  +-------------------- padding --------------------+   |  |
|  |  |                                                |   |  |
|  |  |                   content                      |   |  |
|  |  |            (元素的实际内容区域)                |   |  |
|  |  |                                                |   |  |
|  |  +-------------------------------------------------+   |  |
|  +---------------------------------------------------------+  |
+---------------------------------------------------------------+

跟着做

步骤 1:可视化盒模型各区域

创建 box-model.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>盒模型演示</title>
  <style>
    body { font-family: system-ui, sans-serif; padding: 2rem; background: #f1f5f9; }
    .demo-box {
      width: 200px; height: 100px; padding: 20px; border: 4px solid #cbd5e1;
      margin: 30px; background: #dbeafe;
    }
    .demo-box span {
      display: block; width: 100%; height: 100%; background: #fff;
      display: grid; place-items: center; font-size: 0.875rem;
    }
  </style>
</head>
<body>
  <h1>盒模型可视化</h1>
  <p>蓝色区域是 padding,黄色区域是 margin,白色区域是 content。</p>
  <div class="demo-box"><span>content 区域</span></div>
</body>
</html>

打开页面后按 F12 → Elements → 选中 .demo-box,右侧 Styles 面板下方的「盒模型示意图」实时显示各区域数值。这是调试布局问题的第一现场。

步骤 2:对比 与

content-box
border-box
.box-a { box-sizing: content-box; width: 200px; padding: 20px; border: 4px solid #000; }
.box-b { box-sizing: border-box;  width: 200px; padding: 20px; border: 4px solid #000; }

测量结果:

  • .box-a 总宽度 = 200 + 40 + 8 = 248px
  • .box-b 总宽度 = 200px(padding 和 border 向内压缩 content)

content-box 的 width 只指 content;border-box 的 width 包含 content + padding + border。现代开发统一使用 border-box,因为设置 200px 就占 200px,符合直觉。

步骤 3:全局设置 border-box

*, *::before, *::after {
  box-sizing: border-box;
}

这行代码应出现在每个项目的 CSS 最前面。它重置所有元素(包括伪元素)的盒模型,让 width 和 height 始终包含 padding 和 border。

步骤 4:理解 Margin 折叠(Margin Collapse)

<style>
  .card {
    margin: 20px;
    padding: 16px;
    background: white;
    border: 1px solid #e2e8f0;
  }
</style>
<div class="card">卡片 A</div>
<div class="card">卡片 B</div>

直观上,两张卡片之间应该有 40px 间距(20 + 20)。实际只有 20px——因为相邻块级元素的垂直 margin 会发生折叠,取两者中的较大值,而不是相加。

常见触发场景:

  • 上下相邻的块级元素
  • 父元素与第一个/最后一个子元素之间(如果中间没有 border、padding、inline content 或 clearance 阻隔)
  • 空块级元素自身的上下 margin

解决方案:给其中一个元素加 padding: 1px 或 border: 1px solid transparent 阻断折叠;或使用 Flexbox/Grid 布局(Flex/Grid 容器中的子元素不发生 margin 折叠)。

步骤 5:outline 与 border 的区别

border 占据盒模型空间,影响布局;outline 不占据空间,绘制在 border 外,不影响布局。调试布局时,可用 * { outline: 1px solid red; } 可视化所有元素边界而不破坏布局。

步骤 6:box-shadow 的视觉层级

.card { box-shadow: 0 1px 3px rgba(0,0,0,0.1), 0 4px 6px rgba(0,0,0,0.05); }

多层阴影叠加模拟真实光照。box-shadow 不影响盒模型尺寸,是纯粹的视觉装饰。

讲清楚要点

  1. 盒模型是渲染引擎的计算基础:浏览器为每个元素计算最终占据的矩形区域时,严格遵循 content → padding → border → margin 的层次。任何布局偏差(元素换行、意外滚动条、间距不符预期)都应回到盒模型排查。

  2. box-sizing: border-box 是现代默认值:它让 width/height 的含义与设计稿一致(「这个卡片就是 300px 宽」),避免心算「content + padding + border = 实际宽度」的噩梦。所有主流 UI 框架(Bootstrap 5+、Tailwind、Material UI)都默认启用。

  3. Margin 折叠是特性,不是 Bug:它让连续的段落、列表项之间有合理的自然间距,避免「段落间距突然翻倍」。理解触发条件后,可以通过 padding、border 或 Flex/Grid 布局来规避不需要的折叠。

  4. display 改变盒模型行为:inline 元素不接受 width/height/margin-top/margin-bottom(垂直 margin 无效);inline-block 既保持行内排列又支持完整盒模型;block 独占一行且支持完整盒模型。

  5. 百分比 padding 和 margin 基于父元素宽度:padding-top: 50% 不是基于父元素高度,而是基于父元素宽度。这个特性常被用来实现固定宽高比的容器(如 16:9 视频占位),但现代 CSS 已有 aspect-ratio 属性,更直观。

  6. 最小内容与最大内容:min-content 是元素内容不溢出时的最小宽度(如最长单词),max-content 是内容完全展开不换行的宽度。理解这两个概念对处理响应式文本溢出至关重要。

你可能会懵的地方

  • 「为什么 width: 100% 加了 padding 就超出父容器?」 因为默认 content-box 下,width: 100% 指 content 占父容器 100%,padding 和 border 额外向外扩展。解决方案:全局设置 box-sizing: border-box,或改用 width: auto(默认行为,自动填满可用空间)。

  • 「两个 <div> 上下排列,各设 margin: 20px,中间为什么是 20px 而不是 40px?」 这是 Margin 折叠。相邻块级元素的垂直 margin 会合并,取较大值。如果你需要 40px 间距,可以给其中一个加 margin-bottom: 40px,另一个不加,或改用 Flex/Grid 布局。

  • 「inline 元素为什么不能设置 margin-top?」 规范如此。行内元素的垂直 margin 不影响行高计算,这是为了避免破坏行内文本流的稳定性。如果需要垂直间距,把元素改为 inline-block 或 block,或改用 padding(inline 元素的垂直 padding 有效,但可能覆盖相邻行内容)。

  • 「outline 和 border 都能画边框,什么时候用哪个?」 需要占据布局空间、需要单边不同样式时用 border。需要不破坏布局的调试标记、需要焦点环(focus ring)时用 outline。:focus-visible 的默认样式就是 outline。

  • 「为什么父元素的高度会被子元素的 margin 撑开/影响?」 如果父元素没有 border、padding、inline content 或 clearance,第一个子元素的 margin-top 会「穿透」父元素,作用于父元素外部。解决方案:给父元素加 padding-top: 1px 或 border-top: 1px solid transparent,或设置 overflow: hidden 创建新的块格式化上下文(BFC)。

错法对照

错法问题正解
不设置 box-sizing 就计算宽度width: 300px 实际占据 300+padding+border全局 *, *::before, *::after { box-sizing: border-box; }
用 margin 给 inline 元素加垂直间距无效或表现异常改为 inline-block 或 block
给父元素直接加 margin-top 来撑开与子元素间距触发 margin 折叠,间距不符合预期给父元素加 padding-top 或给子元素加 margin-top 并理解折叠规则
用 border 做焦点指示布局抖动用 outline 或 box-shadow
忽略 min-content 导致文本溢出长单词或 URL 撑破容器设置 overflow-wrap: break-word 或 word-break: break-all
用 padding-bottom: 56.25% 做 16:9 占位代码可读性差,维护困难使用 aspect-ratio: 16 / 9(现代浏览器支持良好)

卡点急救

  1. 元素宽度总是比预期大:检查 box-sizing 是否为 border-box。如果不是,把 padding 和 border 从 width 中扣除,或全局切换为 border-box。

  2. 上下两个元素之间的间距突然消失或翻倍:这是 Margin 折叠。检查两个元素的垂直 margin 值,折叠取较大值。如需精确控制,给其中一个加 padding 或改用 Flex/Grid 布局。

  3. 设置了 height: 100% 但元素没有高度:父元素必须有明确的高度(如 height: 500px 或 height: 100vh)。如果父元素高度由内容决定,子元素的 height: 100% 会解析为 auto。替代方案:使用 Flexbox 的 flex: 1 或 Grid 的 1fr。

面试常问

  • 「标准盒模型和 IE 盒模型(怪异模式)的区别?如何切换?」 标准盒模型(content-box):width 仅指 content 宽度,总宽度 = content + padding + border + margin。IE 盒模型(border-box):width 包含 content + padding + border,总宽度 = width + margin。通过 box-sizing 属性切换,现代开发统一使用 border-box。

  • 「什么是 Margin 折叠?如何避免?」 相邻块级元素的垂直 margin 会合并为单个 margin,取两者中的较大值。触发场景:上下相邻元素、父元素与第一个/最后一个子元素、空块级元素自身。避免方式:给父元素加 padding 或 border;使用 overflow: hidden 创建 BFC;改用 Flexbox 或 Grid 布局(容器内不发生折叠);或给其中一个元素设置 margin-bottom 而另一个不设 margin-top。

  • 「BFC(块格式化上下文)是什么?如何触发?」 BFC 是页面中的一块独立渲染区域,内部元素的布局不影响外部。触发方式:overflow: hidden(或 auto/scroll)、float: left/right、position: absolute/fixed、display: inline-block/table-cell/flex/grid 等。BFC 的典型应用:清除浮动(父元素创建 BFC 可包含浮动子元素)、阻止 margin 折叠、避免文字环绕浮动元素。

自测三问

  1. 一个元素设置 width: 200px; padding: 20px; border: 5px solid; margin: 10px;,在 content-box 和 border-box 下,它在页面上占据的总宽度分别是多少?
  2. 为什么两个相邻的 <div> 各设置 margin: 20px,它们之间的实际间距是 20px 而不是 40px?如何让间距变成 40px?
  3. 如果你发现页面上的元素宽度在 Chrome 和 Firefox 中不一致,首先应该检查哪个 CSS 属性?

小结一句话

盒模型是 CSS 布局的「牛顿定律」——content、padding、border、margin 四层结构决定了每个元素在页面上占据的精确空间;统一使用 border-box 并理解 margin 折叠规则,就能消除 80% 的「布局对不上」问题。

延伸

  • MDN:盒模型详解
  • MDN:Margin 折叠
  • MDN:box-sizing
  • 下一课:Flexbox——一维布局的现代解决方案。
加载本节练习…
← 上一课CSS 选择器与层叠下一课 →Flexbox 布局