先记住这个答案
移动端导航变窄时,flex-flow: row wrap 可以让入口沿行内方向排列,容不下的入口进入下一行;换成 column wrap 则沿纵向先排满一列,再向旁边换列。flex-flow 同时设置方向与换行,省略其中一项时要确认另一个属性是否会被重置为初始值。默认的 row nowrap 只排一行,但项目仍可能收缩。
flex-flow是方向 + 换行的缩写row wrap是最常用的组合column wrap需要固定高度- 默认值
row nowrap不换行
row wrap:最常用的响应式布局
标签列表、商品卡片这类布局几乎都用 row wrap。子项从左到右排列,一行放不下就自动换到下一行。配合百分比宽度或 flex-basis,可以轻松做出一行两列变三列的响应式效果。
.card-list {
display: flex;
flex-flow: row wrap;
gap: 16px;
}
.card {
flex: 0 0 calc((100% - 32px) / 3); /* 两道 16px 间距,三列等宽 */
/* 窄屏可以通过媒体查询改成 50% 或 100% */
}flex: 0 0 calc(...) 表示不伸缩、固定宽度。配合 gap 控制间距,比用 margin 更好控制。
column wrap:固定高度的分栏
column wrap 让子项从上到下排列,超过容器高度就换到下一列。这要求容器有一个固定高度,否则不会换列。
常见场景是移动端底部菜单:容器高度固定,菜单项按两列排列。或者表单里多个字段按两列纵向排列。
需要注意 column wrap 下容器的宽度可能不会被子项撑开。如果容器的宽度是 auto,某些浏览器不会根据列数自动调整宽度。
nowrap:默认行为和溢出处理
flex-flow: row nowrap 是默认值。子项放不下时不会换行,而是靠 flex-shrink(默认是 1)来压缩子项。如果所有子项都设了 flex-shrink: 0,子项就会溢出容器。
导航栏、水平滚动列表这类布局通常用 nowrap,配合 overflow-x: auto 让溢出的内容可以横向滚动。
容易答错的地方
- 把
flex-flow的两个值写反了 flex-flow的值顺序其实无所谓,浏览器能自动识别方向和换行。flex-flow: wrap row和flex-flow: row wrap效果一样。但为了可读性,通常先写方向再写换行。- 以为
column wrap不需要固定高度 column方向下,子项从上到下排列。如果容器高度是auto,它会自动撑高来容纳所有子项,永远不会换列。必须给容器设固定高度,子项才能溢出并换列。
面试官还会怎么问?
flex-flow: row-reverse wrap 的换行方向是什么?
子项从右到左排列,换行方向还是向下。就是说第一行在顶部、子项从右到左,第二行在第一行下面、也是从右到左。如果要换行方向也反转,用 wrap-reverse。
怎么实现一行放两个、第三个单独占一行的布局?
前两个设 flex: 0 0 calc(50% - gap),第三个设 flex: 0 0 100%。row wrap 会自动让第三个换行并占满一行。
flex-flow 和直接写两个属性有什么区别?
功能完全一样,flex-flow 只是缩写。写 flex-flow: row wrap 等于写 flex-direction: row; flex-wrap: wrap。用缩写更简洁,但有些团队的代码规范要求拆开写,便于搜索和覆盖。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。