Flexbox — 一维布局的完整工具箱
Flexbox — 一维布局的完整工具箱
这一章讲现代 CSS 用得最多的布局系统。 它解决一类特定问题: 一行(或一列)里挤着好几个盒子,怎么对齐、怎么均分空间、怎么让某一个盒子把剩余空间吃掉。 「垂直居中」这个困扰了 CSS 十五年的老问题,Flexbox 用三行代码解决了1。
1. 这一章在全书链条里的位置
display(第 05 章)给了「站队」的基本姿势;Flexbox 和 Grid 是 display 的两个高级值
(display: flex / display: grid),站队规则全部升级。两章的分工原则书里写得很直白:
Flexbox 管一维(行或列),Grid 管二维(行和列同时)2——
发现自己在拿 Flex 硬凑网格(一层套一层),就是该换 Grid 的信号3。
2. 顶层全景:父管排法,子管身材
.display: flex 的父容器(Flex Container,伸缩容器)
┌─────────────────────────────────────────────┐
│ [item] [item] [item] ← 子项(Flex Items) │
└─────────────────────────────────────────────┘
│ │ │
├─ 主轴方向:由 flex-direction 定,默认水平 → ← justify-content 管这轴
└─ 交叉轴:与主轴垂直,默认垂直 ↑ ← align-items 管这轴
图说:两个轴是 Flexbox 的全部世界观。对齐属性挂错轴,是本章第一大错。三个名词:伸缩容器是声明了 display: flex 的父元素;伸缩项是它的直接孩子;
主轴是子项排列的方向(默认水平),交叉轴是与它垂直的方向4。
注意「直接孩子」——孙辈不参与分配,这点和 Grid 一样。
3. 核心原理:容器侧的四个旋钮
方向与换行
flex-direction: row(默认)/ row-reverse / column / column-reverse——主轴朝哪5。
flex-wrap: nowrap(默认,挤着也不换行)/ wrap / wrap-reverse——装不下时换不换行6。
对齐:justify 与 align 的分工
justify-content 管主轴(默认即水平):子项在行的哪头、间隔怎么分7:
| 值 | 效果 |
|---|---|
| flex-start(默认) | 挤向起点 |
| flex-end | 挤向终点 |
| center | 居中 |
| space-between | 两头贴边,中间均分 |
| space-around | 每个子项两侧等宽空隙 |
| space-evenly | 所有空隙等宽 |
align-items 管交叉轴(默认即垂直),常用 stretch(默认,拉高到行高)、
center(垂直居中)、flex-start/flex-end8。
记法:justify 是「主轴」,align 是「交叉轴」;一旦 flex-direction: column,
主轴变竖,两个属性管的方向就跟着互换——书里把「justify 与 align 搞混」列为本章头号错误9。
gap 管间距:gap: 20px 让相邻子项之间恰有 20px,比给每个子项配 margin 干净——
margin 会在首尾多出来一块,gap 不会。书里补了一句兼容性注记:
2020 年前的浏览器不支持 Flex 里的 gap,如今已全面可用10。
主轴例子(承上):一行三个盒子,均分间隔
.container {
display: flex;
justify-content: space-between;
gap: 20px;
}子项从起点排到终点,首尾贴边,中间的空隙均分;任何一对相邻子项之间又保底 20px—— 两个属性各管一段,互不打架。
4. 核心原理:子项侧的分配机制
容器管「排法」,子项管「身材」。三个属性合作:
- flex-basis:分配前的基础尺寸,
auto表示按内容。 - flex-grow:有剩余空间时,按份数长大。默认 0——不长。
- flex-shrink:空间不够时,按份数缩小。默认 1——一起缩。
主线例子:侧栏 + 主区,剩余空间全给主区
输入:500px 宽的容器,里面两个子项,要求「侧栏恒定 200px,主区吃掉剩下的」。
.sidebar { flex: 0 0 200px; } /* 不长、不缩、基础 200px */
.content { flex: 1; } /* 份数 1 → 吃掉全部剩余 */走一遍分配:容器 500px。侧栏基础 200px,声明不长不缩,钉死 200px。
剩余 300px。.content 的 flex-grow 是 1,全拿走——主区最终 300px11。
容器缩到 400px 呢?侧栏仍 200(不缩),主区缩到 200(grow 为 0 时的 basis auto
按内容算,收缩按默认 shrink 1 走)——无论容器怎么变,侧栏恒定。
这正是「圣杯布局」里侧栏的写法,后面 Grid 一章会用另一种方式重做它。
三个数字按 grow、shrink、basis 顺序简写成一行 flex: 0 0 200px。
书里建议永远用简写,拆开写又长又容易漏12;最常用两个模板:
flex: 1; /* = 1 1 0%:可长可缩,基础为零,均分剩余 */
flex: 0 0 200px; /* = 钉死 200px */单个子项的特权
align-self 让某一个子项不服从容器的 align-items,单独对齐13;
margin: auto 有个妙用:margin-left: auto 会把这一个子项推到行的尽头——
「导航条最右边放一个退出按钮」的标准做法14。
5. 常见模式速览
书里三个模式,都是上面零件的直接组装:
| 模式 | 关键代码 | 干什么 |
|---|---|---|
| 完美居中 | justify-content: center; align-items: center; | 水平垂直双居中1 |
| 分裂导航 | .logout { margin-left: auto; } | 把一项推到行尾14 |
| 卡片组 | flex-wrap: wrap; gap: 1rem; + 卡片 flex: 1 1 300px | 卡片行自动换行、拉伸、保底 300px15 |
6. 作者的判断与证据
- 「Flexbox 不需要 float 或复杂定位」——定位句,把它定义为现代默认16。
- 「justify 管主轴、align 管交叉轴」的记忆法——教学判断,全书反复用。
- 「用简写 flex 而不是拆开三个属性」——工程断言,理由(更干净可靠)成立12。
- 「老浏览器 gap 不支持」——兼容性事实,带年份(2020 年前)10。
- 证据类型:断言 + 最小例子,无性能或兼容性数据表。
7. 边界与局限
- 没讲
order(子项排序)与flex-flow简写——都是不常用件。 - 没讲 Flex 的二维能力(
align-content多行对齐)——多行场景本书留给 Grid。 - 没讲「Flex 子项的 min-width 默认是 auto,内容太大会撑破容器」这个高频坑
(解法
min-width: 0)——本书未收。
判断(我们的,不是书里的): 本章把「主轴/交叉轴」放在最前面讲是正确顺序—— 这个坐标系一旦建立,后面所有属性都有了挂放的位置;反过来先背属性名的教法, 读者永远要在脑子里翻「justify 是横还是竖」。 如果错,会错在: 对完全没有坐标系概念的读者,「主轴随 flex-direction 变」本身 就需要一个动画才能真懂——静态文字讲到这里是合理终点,再往下必须亲手试。
8. 可带走的
display: flex开世界;主轴 justify、交叉轴 align,换 column 角色互换9。- 子项身材三件套:basis(基础)、grow(长大份数)、shrink(缩小份数),永远用简写12。
flex: 1均分剩余;flex: 0 0 200px钉死尺寸——两个模板覆盖八成场景11。- 间距用
gap,不用 margin——首尾不脏10。 - 单个元素推到行尾:
margin-left: auto(或右推margin-right: auto)14。 - 垂直居中三行:display flex + justify center + align center1。
- 拿 Flex 套娃搭网格时停手——那是 Grid 的活(下一章)3。
9. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 一维布局定位 | Chapter 7: Flexbox Reference | text/08-ch01-1-chapter-overview.txt:7(搜「one-dimensional」) |
| 容器/子项/两轴 | 同上 | text/08-ch01-1-chapter-overview.txt:21(搜「Flex Container」) |
| flex-direction 四值 | 同上 | text/08-ch01-1-chapter-overview.txt:45(搜「row-reverse」) |
| justify-content 六值 | 同上 | text/08-ch01-1-chapter-overview.txt:52(搜「justify-content」) |
| align-items 五值 | 同上 | text/08-ch01-1-chapter-overview.txt:57(搜「align-items」) |
| gap 与居中示例 | 同上 | text/08-ch01-1-chapter-overview.txt:62(搜「gap」) |
| flex-grow/shrink/basis | 同上 | text/08-ch01-1-chapter-overview.txt:80(搜「ability for a flex item to grow」) |
| 侧栏钉死 + 主区吃掉剩余 | 同上 | text/08-ch01-1-chapter-overview.txt:103(搜「flex: 0 0 200px」) |
| justify/align 搞混是头号错 | 同上 | text/08-ch01-1-chapter-overview.txt:147(搜「Confusing justify and align」) |
| gap 的兼容性注记 | 同上 | text/08-ch01-1-chapter-overview.txt:151(搜「pre-2020」) |
| 完美居中 | 同上 | text/08-ch01-1-chapter-overview.txt:113(搜「Perfect Center」) |
| 分裂导航 | 同上 | text/08-ch01-1-chapter-overview.txt:123(搜「Split Navigation」) |
| 卡片组 | 同上 | text/08-ch01-1-chapter-overview.txt:133(搜「Card Group」) |
| 拿 Flex 硬凑网格的警告 | 同上 | text/08-ch01-1-chapter-overview.txt:153(搜「nested flex」) |
Footnotes
-
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:113,搜「Perfect Center」)。原文:「Centering an element both horizontally and vertically.」示例为display: flex; justify-content: center; align-items: center; height: 100vh;。 ↩ ↩2 ↩3 -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:7,搜「single axis」)。原文:「a one-dimensional layout model designed for distributing space along a single axis (either a row or a column)」。 ↩ -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:153,搜「nested flex」)。原文:「If you find yourself using many nested flex containers to create a grid, consider using CSS Grid (Chapter 8) instead.」 ↩ ↩2 -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:21,搜「Flex Container」;:25搜「Main Axis」)。原文:Flex Container 是应用 display: flex 的父元素;Main Axis 默认水平,Cross Axis 垂直。 ↩ -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:45,搜「row-reverse」)。原文:「Values: row (default), row-reverse, column, column-reverse.」 ↩ -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:47,搜「flex-wrap」)。原文:「Controls whether items should wrap to multiple lines.」 ↩ -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:52,搜「justify-content」)。原文:「Aligns items along the Main Axis.」值为flex-start (default), flex-end, center, space-between, space-around, space-evenly。 ↩ -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:57,搜「align-items」)。原文:「Aligns items along the Cross Axis.」默认值 stretch。 ↩ -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:147,搜「Confusing justify and align」)。原文:「Remember: Justify is for the Main Axis (usually horizontal), Align is for the Cross Axis (usually vertical). If you change flex-direction to column, their roles effectively swap.」 ↩ ↩2 -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:151,搜「pre-2020」)。原文:「In older browsers (pre-2020), gap didn't work in Flexbox. Today it is widely supported and much better than using margins.」 ↩ ↩2 ↩3 -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:103,搜「flex: 0 0 200px」)。原文:「.sidebar { flex: 0 0 200px; } /* Won't grow, won't shrink, stays 200px / .content { flex: 1; } / Grows to fill all remaining space */」。剩余空间的计算(500px 容器 → 主区 300px)是按这个分配规则走的演示,容器宽度 500px 是为演示设的数。 ↩ ↩2 -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:149,搜「shorthand」)。原文:「Writing flex: 1 is cleaner and more reliable than setting flex-grow, flex-shrink, and flex-basis separately.」 ↩ ↩2 ↩3 -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:106,搜「align-self」)。原文:「Allows the default alignment (from align-items) to be overridden for a single item.」 ↩ -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:123,搜「Split Navigation」)。原文:「Pushing a specific item (like a "Logout" button) to the far right.」,.logout { margin-left: auto; }。 ↩ ↩2 ↩3 -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:133,搜「Card Group」)。原文:「Creating a row of cards that wrap and fill the space equally.」,卡片写flex: 1 1 300px。 ↩ -
出处:「Chapter 7: Flexbox Reference」(
text/08-ch01-1-chapter-overview.txt:7,搜「modern standard」)。原文:「It is the modern standard for aligning elements, handling responsive resizing, and distributing space between items without needing floats or complex positioning.」 ↩