Menu

CSS flex-wrap 和 flex-direction:行、列与换行

flex-wrap 决定 flex 项目是挤在一行里还是换到下一行,flex-direction 决定它们按行还是按列排列。通过实时示例学习这两个属性、flex-flow 简写、align-content,以及一行不用媒体查询的响应式卡片。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

flex-wrap:一行,或者需要几行就几行

默认情况下,flex 容器把所有项目放在同一行(flex-wrap: nowrap),并收缩它们以适应宽度。flex-wrap: wrap 则让项目保持自己的尺寸,放不下时换到下一行:

每个项目需要 100px,五个项目放在一个 340px 宽的盒子里。五个项目加上四个 8px 的间距需要 532px,所以在不换行时,每个项目被挤到约 62px,因为 flex 项目默认会收缩。设置 wrap 后,它们保持 100px:第一行放得下三个,另外两个移到第二行。

flex-wrap 的取值

值效果
nowrap(默认值)只有一行。项目会收缩,无法再收缩时就溢出容器
wrap放不下的项目在下方开始新的一行
wrap-reverse同上,但新行向上堆叠:第一行在最下面

看项目如何换行

拖动滑块改变容器的宽度。读数会统计行数,并显示每行有几个项目:

在 400px 时,四个 90px 的项目加上三个 8px 的间距(384px)能放进一行,所以结果是 4 + 2。往 620px 拖,六个项目都能放进一行;往 120px 拖,每个项目都各占一行。

flex-direction:行还是列

flex-direction 设置项目排列的方向,也就是主轴:

值项目排列方式第一个项目
row(默认值)并排,沿书写方向在行的开头
row-reverse并排,方向相反在行的末尾
column堆叠,从上到下在最上面
column-reverse堆叠,从下到上在最下面

在两个 row 盒子中,项目被拉伸到盒子的全部高度,因为 align-items: stretch 作用于行的交叉方向。在 column 盒子中,出于同样的原因,项目被拉伸到全部宽度。轴转向了,所有对齐属性也跟着转向(justify-content 页面详细展示了这一点)。

flex-flow:一行写完两个属性

flex-flow 是先写 flex-direction、再写 flex-wrap 的简写:

.cards { flex-flow: row wrap; }      /* flex-direction: row; flex-wrap: wrap; */
.stack { flex-flow: column nowrap; } /* flex-direction: column; flex-wrap: nowrap; */

用 wrap 实现不需要媒体查询的响应式卡片

用 flex: 1 1 180px 给每个项目一个初始尺寸,并让这一行可以换行。每个项目会增长以填满所在的行,当一行再也放不下一个 180px 的项目时,下一个项目就会换行:

在大约 800px 宽的预览中,第一行能放下三张卡片(每张约 253px),最后两张共用第二行,每张增长到约 386px。这就是 flexbox 的工作方式:每一行各自分配自己的空间,所以较短的最后一行中的卡片会比上面的更宽。如果你希望最后一张卡片和其他卡片一样宽,就改用 grid 加 repeat(auto-fill, minmax(180px, 1fr))(见 grid 页面)。

align-content:设置行与行之间的间距

当容器换行并且比各行加起来更高时,align-content 决定各行放在哪里。它接受和 justify-content 相同的值,另外还有 stretch:

在第一个盒子中,两行都位于顶部。在第二个盒子中,第一行在顶部,第二行在底部,所有多余的高度都在两行之间。

反向排列与无障碍

row-reverse、column-reverse 和 wrap-reverse 只改变项目绘制的位置。屏幕阅读器和 Tab 键仍然按照 HTML 中的顺序,所以键盘用户浏览项目的方向会和他看到的方向相反。反向排列只用于视觉效果;当顺序有实际含义时,请在 HTML 中调整顺序。

常见错误

  • 项目收缩而不是换行。 带 flex: 1 的项目从 0 的 flex-basis 开始,会挤进同一行。给它们一个真实的基准尺寸,例如 flex: 1 1 200px。
  • 把 flex-wrap 写在项目上。 它应该写在 flex 容器上。
  • 用 align-items 设置换行后各行的间距。 它对齐的是每行内的项目;各行本身要用 align-content 移动。
  • 最后孤零零的一个项目被拉伸到整行。 这是单个项目所在行上的 flex-grow 造成的。如果每张卡片都必须一样宽,请用 grid。
  • 以为 flex-direction: column 会填满高度。 列方向的容器只和内容一样高,除非你给它设置 height,所以 justify-content 没有空间可以发挥作用。

常见问题

flex-wrap: wrap 有什么作用?

它允许 flex 项目在一行放不下时换到新的一行。在默认的 nowrap 下,项目会留在同一行并收缩,如果无法再收缩,就会溢出容器。

为什么 flex-wrap 不生效?

只有当项目的初始尺寸加起来超过容器时才会换行。带 flex: 1 的项目从 0 的 flex-basis 开始,所以永远不会换行;给它们一个真实的初始尺寸(flex: 1 1 200px 或 width: 200px)。另外检查 flex-wrap 是不是写在了 flex 容器上,而不是项目上。

flex-direction 的 row 和 column 有什么区别?

row(默认值)沿书写方向把项目并排放置,column 把它们从上到下堆叠。主轴也随之转向,所以在列方向上,justify-content 作用于垂直方向,align-items 作用于水平方向。

flex-flow 是什么?

它是把 flex-direction 和 flex-wrap 写在一条声明里的简写:flex-flow: row wrap; 等同于 flex-direction: row; flex-wrap: wrap;。

align-items 和 align-content 有什么区别?

align-items 在每一行内放置项目。align-content 在容器内放置各行本身,所以只有当容器设置了 flex-wrap: wrap 并且比各行加起来更高时,它才有作用。

Coddy 编程语言插图

和 Coddy 一起学编程

开始