CSS Flexbox 布局速查表 - Flexbox 弹性布局属性大全
面向还在用 float 或 inline-block 折腾居中和等宽行的开发者。Flexbox 是快速做一行或一列布局的现代方案。最常混淆的点是 Flexbox 是单维的,且 justify-content 与 align-items 作用在两根不同的轴上。读完能把任意内容居中、搭出工具栏和自动换行的卡片行,并用 flex-grow/flex-shrink/flex-basis 精控尺寸而不靠试错。
典型使用场景
面向做布局调整时不想再和 float、绝对定位纠缠的前端开发者。Flexbox 的难点几乎全在两条轴的区分上:flex-direction 决定主轴,align-items 作用于交叉轴,一旦主轴翻转,对齐方向的含义就跟着变。本表把容器属性(方向、换行、间距)、主轴对齐(justify-content)、交叉轴对齐(align-items / align-self / align-content)和项目属性(flex-grow / shrink / basis 的简写)分层排开,再给出水平垂直居中、两端对齐、粘性页脚、响应式卡片网格这几套可直接复用的布局组合,最后的易错点解释了 flex: 1 为什么不是 1 1 auto、为什么 column 布局里 align-items 看起来在控制水平方向。
容器属性 8
display: flexdisplay: inline-flexflex-direction: rowflex-direction: columnflex-direction: row-reverseflex-direction: column-reverseflex-wrap: wrapflex-flow: row wrap间距与主轴对齐 8
gap: 16pxrow-gap: 16pxcolumn-gap: 16pxjustify-content: flex-startjustify-content: centerjustify-content: flex-endjustify-content: space-betweenjustify-content: space-around交叉轴对齐 7
justify-content: space-evenlyalign-items: stretchalign-items: flex-startalign-items: centeralign-items: flex-endalign-items: baselinealign-content: center项目属性 10
flex-grow: 1flex-shrink: 1flex-basis: 200pxflex: 1flex: 0 0 200pxflex: autoflex: nonealign-self: flex-endorder: 1order: -1常用布局模式 6
justify-content: center; align-items: centerjustify-content: space-betweenflex: 1margin-left: automin-height: 100vhflex: 1 0 auto响应式技巧 5
flex-wrap: wrapflex-basis: 200px; flex-grow: 1flex-wrap: wrap-reverse@media (max-width: 768px) { flex-direction: column }flex: 1 1 100%参数矩阵
| 参数 | 作用 | 示例 |
|---|---|---|
display: flex | 启用弹性布局,容器变为块级 | display: flex |
display: inline-flex | 启用弹性布局,容器按行内级参与排版 | display: inline-flex |
flex-direction: row | 主轴为水平行方向(默认值) | flex-direction: row |
flex-direction: column | 主轴为垂直方向,此时交叉轴变为水平 | flex-direction: column |
flex-direction: row-reverse | 主轴水平但排列方向反转 | flex-direction: row-reverse |
flex-direction: column-reverse | 主轴垂直但排列方向反转 | flex-direction: column-reverse |
flex-wrap: wrap | 允许项目换行,默认 nowrap 不换行 | flex-wrap: wrap |
flex-wrap: wrap-reverse | 换行时交叉轴方向反转 | flex-wrap: wrap-reverse |
flex-flow: row wrap | flex-direction 与 flex-wrap 的简写 | flex-flow: row wrap |
gap / row-gap / column-gap | 项目间距,可分别控制两个方向 | gap: 16px |
justify-content: flex-start | 主轴起始对齐(默认) | justify-content: flex-start |
justify-content: center | 主轴居中对齐 | justify-content: center |
justify-content: flex-end | 主轴末尾对齐 | justify-content: flex-end |
justify-content: space-between | 两端对齐,项目间空隙均分 | justify-content: space-between |
justify-content: space-around | 每个项目两侧等距,端部空隙较小 | justify-content: space-around |
justify-content: space-evenly | 所有空隙完全相等 | justify-content: space-evenly |
align-items: stretch | 交叉轴拉伸填满(默认) | align-items: stretch |
align-items: center | 交叉轴居中对齐 | align-items: center |
align-items: baseline | 交叉轴按文本基线对齐 | align-items: baseline |
align-content: center | 多行内容整体在交叉轴上的对齐,需配合换行 | align-content: center |
flex-grow | 放大比例,0 表示不放大 | flex-grow: 1 |
flex-shrink | 缩小比例,默认 1 表示允许压缩 | flex-shrink: 1 |
flex-shrink: 0 | 禁止被压缩,保持基础尺寸 | flex: 0 0 200px |
flex-basis: 200px | 分配剩余空间前的初始主轴尺寸 | flex-basis: 200px |
flex: 1 | 简写 1 1 0%,等分剩余空间 | flex: 1 |
flex: 0 0 200px | 简写:不放大不压缩,固定 200px | flex: 0 0 200px |
flex: auto | 简写 1 1 auto,按内容起始再分配 | flex: auto |
flex: none | 简写 0 0 auto,完全不伸缩 | flex: none |
flex: 1 1 100% | 占满整行,强制换到下一行 | flex: 1 1 100% |
flex: 1 0 auto | 固定基础尺寸且不压缩,常用于侧边栏 | flex: 1 0 auto |
align-self | 覆盖父容器的 align-items,单独控制某一项 | align-self: flex-end |
order | 视觉排列顺序,默认 0,可为负值 | order: -1 |
margin-left: auto | 用外边距把项目推到主轴末尾 | margin-left: auto |
min-height: 100vh | 配合 column 容器与 flex: 1 实现粘性页脚 | min-height: 100vh |
@media (max-width: 768px) { flex-direction: column } | 窄屏时把横向布局切为纵向 | @media (max-width: 768px) { flex-direction: column } |
易错点与避坑指南
现象父容器写了 flex: 1 子项却被压扁,内容溢出或高度塌陷。
原因flex: 1 等价于 flex: 1 1 0%,shrink 分量为 1 表示允许被压缩到内容尺寸以下;垂直方向的主内容区没显式给基准尺寸就会被挤没。
处置需要不被压缩时改用 flex: 1 0 auto,或在纵向撑开场景给子项写 flex-grow: 1 并给父容器 min-height: 100vh。
现象align-items 明明写在容器上,却看不出任何水平居中的效果。
原因容器的 flex-direction 是 column,此时主轴变成垂直方向,交叉轴随之变为水平,align-items 控制的正是水平方向;而开发者想控制的是垂直方向。
处置在 column 容器里要垂直居中应改用 justify-content: center;反之在 row 容器里垂直居中用 align-items: center。
现象多行 flex 容器里各行之间的分布不受 justify-content 控制,行整体贴在一起。
原因justify-content 只作用于主轴上的项目分布,多行整体在交叉轴上的分布由 align-content 控制。
处置给容器加 align-content: center 之类的取值来分配交叉轴空间,同时确认 flex-wrap: wrap 确实生效。
现象给项目加了 flex-direction / gap 却完全没反应。
原因这些属性作用在容器上,加在了子项元素上;子项只能用 flex、flex-basis、align-self、order 这类项目属性。
处置把 flex-direction、flex-wrap、gap、justify-content 移到父容器声明,子项只保留 flex 与 align-self。
现象使用 order 改变顺序后,Tab 键的焦点顺序与视觉顺序不一致。
原因order 只改变视觉排列,不改变 DOM 与焦点顺序,屏幕阅读器和键盘导航仍按文档顺序走。
处置尽量在 DOM 结构上直接排序,不用 order 制造视觉差异;必须用时同时检查键盘可达性。
现象flex-wrap: wrap 配了 flex-basis 却没有换行,窗口缩窄时卡片被压扁而不是换行。
原因子项的 min-width 默认是 auto,内容较长时不允许被压缩到内容宽度以下,容器不会认为需要换行。
处置给卡片加 min-width: 0(或按内容类型给合适的 min-width),让 flex-basis 成为真实生效的换行依据。
现象页脚没有吸底,内容少时整页高度塌缩。
原因只给页脚设了 margin-top: auto,但父容器不是 flex 容器,或没有指定 min-height。
处置父容器写 display: flex; flex-direction: column; min-height: 100vh,中间主内容区写 flex: 1 撑开剩余空间。
排障路径
1确认容器确实进入了弹性布局
display: flex若子项仍按普通块级排列,说明这条声明没落到实际父容器上,检查选择器是否命中。
2用 justify-content 确认主轴方向的居中
justify-content: center; align-items: center两条同时写可实现水平垂直居中,但要先确定当前 flex-direction 到底是 row 还是 column。
3确认换行是否生效
flex-wrap: wrap; flex-basis: 200px; flex-grow: 1这组值构成响应式卡片网格:基础宽 200px、有余量就放大、放不下就换行。
4实现粘性页脚的完整容器写法
display: flex; flex-direction: column; min-height: 100vh主内容区再写 flex: 1,内容不足一屏时页脚也会被推到最底部。
5窄屏切列布局
@media (max-width: 768px) { flex-direction: column }视口宽度不超过 768px 时主轴转为垂直,横向排列改为纵向堆叠。
6单项覆盖容器的对齐方式
align-self: flex-end用于在 align-items: center 的容器里把某个按钮单独推到末尾。
命令示例
水平垂直双向居中
.box {
display: flex;
justify-content: center;
align-items: center;
height: 240px;
}justify-content 管主轴、align-items 管交叉轴;只写 display: flex 时项目全挤在左上角,页面看起来像样式没生效。
导航栏两端对齐 + 单项推到末尾
.nav {
display: flex;
align-items: center;
justify-content: space-between;
}
.nav .logout {
margin-left: auto;
}space-between 在只有两个子元素时等价于两端对齐;元素变多后需要靠 gap 或 margin-left: auto 来控制间距,否则分布会随 DOM 结构调整而变化。
响应式卡片网格:wrap + basis + grow
.grid {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.grid > .card {
flex: 1 1 200px;
}
@media (max-width: 768px) {
.grid { flex-direction: column; }
}flex: 1 1 200px 表示以 200px 为基准、可伸缩,超出容器宽度时自动换行;这比写死百分比宽度省掉大部分断点。
粘性页脚:内容区用 flex: 1 撑开
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main { flex: 1; }flex: 1 实际是 1 1 0%,即先按 0 计算再吃掉剩余空间,所以页脚永远贴在视口底部而不会被短内容顶上来。
用 order 调整视觉顺序,配合 align-content 排多行
.grid {
display: flex;
flex-wrap: wrap;
align-content: center;
gap: 8px;
}
.grid .featured { order: -1; }order 只改视觉顺序,不改 DOM/tab 顺序;把它当作无障碍问题的解法会让键盘与读屏用户拿到错误的阅读顺序。
常见坑与注意事项
- Flex 项目默认 min-width: auto,长 URL、不换行的代码块或表格会把容器撑破且父级无法收缩,表现为横向滚动条莫名出现;给项目加 min-width: 0 才让内部文本能正常省略或换行。
- flex: 1 等价于 1 1 0% 而不是「平分内容宽度」,与 flex: 1 1 auto 在有内容基准时排布不同;从 auto 切到 0% 会让原本对齐的元素突然错位。
- flex-wrap: wrap 换行后 align-content 默认是 stretch,行与行之间会被拉开到容器高度,看起来像 margin 失效;想要紧凑的行间距要显式写 align-content: flex-start。
- 同时用 margin 和 gap 控制子项间距时,两套机制叠加且 margin 不参与剩余空间分配,很容易出现「最后一个多出一段空白」;同一维度只用其中一种。
- flex 容器会建立新的格式化上下文,position: absolute 的子元素以该容器为包含块而非视口;依赖视口定位的下拉/弹层移进 flex 容器后位置全错。
- overflow: hidden 放在 flex 容器上只裁掉超出部分,容器本身仍按内容最小尺寸计算,溢出依旧会顶开父布局;真正需要约束的是子项的 min-width/min-height。
提示
- flex: 1 是 flex: 1 1 0% 的简写,表示等分剩余空间。
- align-items 是交叉轴对齐,flex-direction: column 时交叉轴变为水平方向。
- gap 属性替代了旧的 margin 技巧,更简洁地设置项目间距。
- flex-wrap: wrap 配合 flex-basis 可以实现响应式网格布局。
- flex 简写优先使用,单独设置 flex-grow/shrink/basis 容易覆盖预期行为。
常见问题
flex: 1 到底等于什么?为什么它能把剩余空间吃掉?
flex: 1 是 flex: 1 1 0% 的简写,三个数字依次对应 flex-grow、flex-shrink、flex-basis。flex-basis: 0% 表示初始尺寸为零,于是容器先把主轴空间全部当作剩余空间,再按 grow 比例 1:1 分给每个写了 flex: 1 的项目,因此看起来像「等分」。对比 flex: auto(1 1 auto)保留了内容原始尺寸,短文本项目会显得更小;flex: 0 0 200px 则完全不参与伸缩,宽度锁死 200px。
为什么设了 align-items: center 之后,容器高度塌成内容高度了?
因为 align-items 是交叉轴对齐,而交叉轴是哪条线由 flex-direction 决定。flex-direction: row(默认)时交叉轴是垂直方向,align-items: center 让项目按自身内容高度垂直居中,容器高度自然收缩到最高子项。改成 align-items: stretch(默认值)子项才会被拉伸填满容器。另一个常见误区:column 布局下交叉轴变成水平方向,此时 align-items: center 是在水平方向居中,垂直居中得用 justify-content: center。
卡片列表怎么做到不用 media query 就自动换行成网格?
关键是 flex-wrap: wrap 加 flex-basis。容器设 display: flex; flex-wrap: wrap; gap: 16px,每个卡片写 flex: 1 1 200px:flex-basis: 200px 给出理想宽度,flex-grow: 1 让同一行的卡片撑满剩余空间,flex-shrink: 1 则在窗口变窄时允许收缩。窗口足够宽时一行排满并被拉伸;变窄到放不下 200px 时自动换到下一行,形成响应式网格,无需任何 @media 规则。
space-between、space-around、space-evenly 的视觉差别在哪?
三者都是 justify-content 的主轴分配方式,但余量处理规则不同。space-between 把首尾贴边、中间均分,导航栏左右分布常用;space-around 让每个项目两侧各有等量间距,因此最外侧间距是中间间距的一半;space-evenly 则让所有相邻元素之间以及两端到容器的间距完全相等。做卡片行、按钮组时,如果发现边距和中间空隙不一致,就该在这三个之间换。
怎么用 flex 实现「内容撑不满时贴底、撑满时正常」的粘性页脚?
给外层容器设 display: flex; flex-direction: column; min-height: 100vh,让主轴变成垂直方向;再把中间的主要内容区写成 flex: 1,它的 flex-grow 会吃掉所有剩余高度,把页脚始终推到容器底部。内容超过一屏时容器自然被撑高,页脚跟在内容后面而不会重叠。若页脚元素设置了 flex-shrink 导致被压扁,可给正文区改用 flex: 1 0 auto 固定基础尺寸且不压缩。
由 巧匠 维护
公开更新于 2026年7月21日,内容持续校对官方文档。