上篇回顾:2.1-01 讲了 HTML 语义化的三大收益对象(SEO/无障碍/可维护性)和 DOM 模型 + 浏览器渲染流水线。本篇进入 CSS------后端工程师在前端最大的痛苦来源。样式不生效、布局错位、垂直居中搞不定......根因都是没系统理解 CSS 布局体系。

一、开篇:一个 CSS 让后端崩溃的瞬间
后端工程师写 CSS 的典型过程:
- 写
margin: 0 auto居中 → 不生效 - 加
text-align: center→ 文字居中了但 div 没居中 - 查文档说用
flex→ 加了display: flex但全乱了 - 改回
float: left→ 又出现高度塌陷 - 怒删 CSS,
position: absolute; top: 50%; left: 50%→ 居中了但偏右下 - 查到要加
transform: translate(-50%, -50%)→ 终于居中 - 改需求说要响应式 → 崩溃
这个过程暴露的问题:用试错法写 CSS,不理解布局原理。本篇把盒模型、文档流、定位、Flex、Grid 一次讲透,让你从「试错」升级到「知道用什么」。
二、盒模型:一切布局的基础
2.1 标准盒模型 vs IE 盒模型
标准盒模型(box-sizing: content-box):
width = 内容宽度
总宽 = width + padding + border + margin
IE 盒模型(box-sizing: border-box):
width = 内容 + padding + border
总宽 = width + margin(width 已含 padding 和 border)
推荐全局用 border-box:
css
* {
box-sizing: border-box;
}
原因:width: 100px 就是最终占 100px,加 padding 不会撑大。符合直觉。
2.2 margin 合并
垂直方向相邻的 margin 会合并(取较大值):
html
<div style="margin-bottom: 20px">A</div>
<div style="margin-top: 30px">B</div>
<!-- A 和 B 之间间距是 30px 不是 50px -->
解决方案 :用 padding 代替 margin,或给父元素加 overflow: hidden(触发 BFC)。
三、选择器优先级
CSS 规则可能冲突,优先级计算规则:
!important > 内联 > ID > 类/属性/伪类 > 标签/伪元素 > 通配符
用四位数字表示:(内联, ID, 类, 标签)
| 选择器 | 优先级 |
|---|---|
#header .title |
(0,1,1,0) |
.nav .item.active |
(0,0,3,0) |
div > p |
(0,0,0,2) |
* |
(0,0,0,0) |
实践建议 :不要用 !important(除非覆盖第三方库),优先级控制在类选择器级别。
四、文档流:默认的布局规则
4.1 三种流
| 流 | 元素 | 特点 |
|---|---|---|
| 普通流 | 默认 | 块级换行、行内不换行 |
| 浮动流 | float |
脱离普通流,文字环绕 |
| 定位流 | position |
完全脱离文档流 |
4.2 块级 vs 行内 vs 行内块
| 类型 | 宽高 | 换行 | 典型 |
|---|---|---|---|
| block | 可设 | 换行 | div、p、h1 |
| inline | 不可设(由内容决定) | 不换行 | span、a |
| inline-block | 可设 | 不换行 | img、button |
五、定位 position
| 值 | 说明 | 用途 |
|---|---|---|
| static | 默认 | 普通流 |
| relative | 相对自身原位置 | 微调位置、做 absolute 的参照 |
| absolute | 相对最近的非 static 祖先 | 弹窗、提示框 |
| fixed | 相对浏览器窗口 | 固定导航、回到顶部 |
| sticky | 滚动到阈值后固定 | 表头吸顶 |
css
/* 经典:子绝父相 */
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 居中 */
}
六、层叠上下文
为什么 z-index: 9999 不生效?因为不是所有元素都有层叠上下文。
创建层叠上下文的条件:
position: absolute/relative+z-index ≠ autoposition: fixed/stickyopacity < 1transform ≠ noneflex/grid容器的子项 +z-index ≠ auto
规则:子元素的 z-index 只在父元素的层叠上下文内有效。父元素 z-index 低,子元素 z-index 再高也压不过别人家的父元素。
七、Flex 布局:现代布局首选
7.1 Flex 心智模型
┌─────────────────────────────┐
│ 主轴(main axis)→ │
│ ┌───┐ ┌───┐ ┌───┐ │
│ │ A │ │ B │ │ C │ ← 交叉轴 │
│ └───┘ └───┘ └───┘ (cross)│
│ │
└─────────────────────────────┘
Flex 容器的属性控制主轴方向和对齐,子项的属性控制自身伸缩。
7.2 容器属性
css
.container {
display: flex;
flex-direction: row; /* row | column | row-reverse | column-reverse */
justify-content: center; /* 主轴对齐:flex-start | center | space-between | space-around */
align-items: center; /* 交叉轴对齐:flex-start | center | stretch | baseline */
flex-wrap: wrap; /* 是否换行 */
gap: 16px; /* 间距(现代 CSS) */
}
7.3 子项属性
css
.item {
flex-grow: 1; /* 放大比例:剩余空间分配 */
flex-shrink: 0; /* 缩小比例:0 不缩小 */
flex-basis: 200px;/* 基准尺寸 */
/* 简写:flex: 1 0 200px */
}
7.4 垂直居中:为什么是经典题
「垂直居中」考的不是记忆,是对 CSS 布局体系全面性的检验。一个能说出 5 种垂直居中方案的人,说明他理解了定位、Flex、Grid、表格等多种布局。
css
/* 方案一:Flex(推荐) */
.parent { display: flex; align-items: center; justify-content: center; }
/* 方案二:Grid */
.parent { display: grid; place-items: center; }
/* 方案三:绝对定位 + transform */
.child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
/* 方案四:绝对定位 + margin auto */
.child { position: absolute; inset: 0; margin: auto; width: 100px; height: 100px; }
/* 方案五:行内对齐 */
.parent { line-height: 200px; text-align: center; }
.child { display: inline-block; vertical-align: middle; }
八、Grid 布局:二维布局之王
Flex 是一维的(一行或一列),Grid 是二维的(行+列同时控制)。
css
.grid {
display: grid;
grid-template-columns: 200px 1fr 200px; /* 三列:固定 | 自适应 | 固定 */
grid-template-rows: 60px 1fr 40px; /* 三行 */
gap: 16px;
}
.header { grid-column: 1 / 4; } /* 跨三列 */
.sidebar { grid-row: 2 / 4; } /* 跨两行 */
适合整体页面骨架布局,Flex 适合组件内部布局。两者配合使用。
九、响应式设计
css
/* 媒体查询 */
@media (max-width: 768px) {
.container {
flex-direction: column; /* 小屏变纵向 */
}
}
/* 现代方案:CSS 容器查询 */
.card-container { container-type: inline-size; }
@container (max-width: 400px) {
.card { flex-direction: column; }
}
十、所有布局本质上在解决什么矛盾
布局的本质是:在有限的视口空间里,安排不定数量、不定尺寸的元素,让它们在不同屏幕下都合理展示。
| 布局方案 | 解决的矛盾 |
|---|---|
| 普通流 | 默认排列不够灵活 |
| 浮动 | 文字环绕图片 |
| 定位 | 脱离文档流精确定位 |
| Flex | 一维方向的灵活分配 |
| Grid | 二维方向的精确控制 |
| 响应式 | 不同屏幕尺寸适配 |
没有「最好的布局方案」,只有「最适合场景的方案」。
十一、小结表
| 概念 | 核心 | 易踩坑 |
|---|---|---|
| 盒模型 | border-box 推荐 | margin 合并 |
| 选择器 | 优先级四位数字 | 滥用 !important |
| 文档流 | 块级换行行内不换 | float 高度塌陷 |
| 定位 | 子绝父相 | z-index 不生效(层叠上下文) |
| Flex | 主轴+交叉轴 | 忘记设 flex-direction |
| Grid | 二维布局 | 和 Flex 混淆 |