flex-wrap 是控制换行的唯一开关,取值为 nowrap(默认,不换行)、wrap(正向换行)或 wrap-reverse(反向换行),仅决定是否折行,不干预单行内排列;换行后需用 align-content 控制多行在交叉轴的分布,且仅在多行时生效;flex-basis 与 flex-shrink 共同影响换行时机,设 flex-shrink: 0 和显式 flex-basis 可确保按预期宽度换行。

flex-wrap 是控制换行的唯一开关
flex-wrap 是 flex-direction 之后决定子元素是否折行的关键属性,它不控制单行内如何排列,只决定“超出容器时要不要另起一行”。默认值是 nowrap,即强制单行——哪怕子元素总宽度远超容器,也会被压缩甚至溢出。
常见错误是以为加了 flex: 1 或设了 width 就能自动换行,其实完全没用;只要 flex-wrap: nowrap(或没显式设置),Flex 容器就坚决不折行。
可选值只有三个:
-
nowrap:不换行(默认) -
wrap:换行,新行在主轴方向按顺序堆叠(比如row下向下堆) -
wrap-reverse:换行,但新行反向堆叠(比如row下向上堆)
换行后,交叉轴对齐要用 align-content
很多人混淆 align-items 和 align-content。前者只对单行内所有子项的交叉轴位置生效;后者才真正控制多行之间在交叉轴上的分布方式。
比如容器设了 flex-direction: row; flex-wrap: wrap;,子元素撑出了 3 行,那么:
立即学习“前端免费学习笔记(深入)”;
-
align-items: center→ 每行内的子项都垂直居中 -
align-content: space-between→ 第 1 行顶对齐、第 3 行底对齐、中间行等距分配剩余空间
注意:align-content 在仅有一行时无效——此时它完全不起作用,别指望靠它调单行对齐。
flex-basis + flex-shrink 组合影响换行时机
换行不是看“总宽度超没超”,而是看“各子项在不压缩前提下的自然宽度总和”是否溢出。这个“自然宽度”由 flex-basis 决定(默认是 auto,即内容宽或 width 值)。
容易踩的坑:
- 子项写了
width: 200px,但父容器flex-wrap: wrap却不换行 → 很可能因为该子项的flex-shrink: 1(默认)让它被压缩了,没触发换行条件 - 想让子项严格按固定宽度换行?把
flex-shrink: 0加上,并显式设flex-basis: 200px -
flex: 1等价于flex: 1 1 0%,其中0%会让flex-basis失效,实际表现接近“均分剩余空间”,不适合做换行依据
移动端多行卡片布局的典型写法
比如 3 列响应式卡片,在小屏下自动变成单列,中屏双列,大屏三列:
.container {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.card {
flex: 0 0 calc(33.333% - 10.666px); /* 3列,扣掉gap影响 */
}
@media (max-width: 768px) {
.card {
flex-basis: 100%; /* 强制单列 */
}
}关键点:用 flex-basis 控制每项“最小不压缩宽度”,配合 flex-wrap 触发换行;gap 要单独算进宽度里,否则最后一列容易掉下去。
换行逻辑本身简单,但实际效果常被 flex-shrink、box-sizing、gap 的计算细节悄悄破坏。调试时先确认 flex-wrap 确实生效,再检查每一项的最终渲染宽度是否真的超出了容器可用空间。










