前言
Flex 布局里有两个很容易混淆的属性:
1 | align-items: center; |
它们看起来都和“交叉轴对齐”有关,也都经常被写在 flex 容器上。
但它们控制的对象完全不同:
| 属性 | 控制对象 | 什么时候生效 |
|---|---|---|
align-items |
每一行里的 flex item | 只要有 flex item 就会生效 |
align-content |
多行 flex line 之间的整体分布 | 必须开启换行,并且真的产生多行 |
一句话总结:
align-items管 item,align-content管 line。
先理解两个方向
Flex 布局有两个轴:
- 主轴:由
flex-direction决定,默认是从左到右。 - 交叉轴:和主轴垂直,默认是从上到下。
默认情况下:
1 | .container { |
这时:
- 主轴是水平方向。
- 交叉轴是垂直方向。
所以很多人说:
align-items是控制垂直居中。
这个说法只在默认 flex-direction: row 时成立。更准确的说法应该是:
align-items控制 flex item 在交叉轴上的对齐方式。
align-items 控制的是 item
看一个最常见的例子:
1 | .container { |
如果容器里只有一个元素:
1 | <div class="container"> |
这个元素依然会垂直居中。
原因很简单:
align-items 控制的是每个 item 在当前 flex line 里的交叉轴位置。
只要有 item,它就有东西可以控制。
align-content 控制的是多行之间
再看这个例子:
1 | .container { |
很多人以为只要写了:
1 | flex-wrap: wrap; |
align-content 就一定会生效。
其实不是。
flex-wrap: wrap 只是允许换行,但不代表已经换行。
align-content 真正需要的是:
- 开启换行:
flex-wrap: wrap - 实际产生多行:内容宽度超过容器宽度,真的排成两行或更多行
如果容器里只有一个元素,或者所有元素都在同一行里,那么页面上只有一条 flex line。
这时没有“多行之间”的空间可以分配。
所以 align-content 看起来就像没有生效。
Demo 1:只有一行时,align-content 不明显
下面这个 demo 同时写了:
1 | align-items: center; |
但容器里只有一个 item,所以真正能看出效果的是 align-items。
只有一个 item:align-items 可以让 item 垂直居中,align-content 没有多行可控制
Demo 2:真的产生多行后,align-content 才开始工作
现在让容器里出现多个 item,并且每个 item 宽度都比较大。
它们放不进一行,于是会变成多行:
1 | .container { |
这时 align-content: center 控制的是所有行组成的整体,让这些 flex line 在交叉轴上居中。
多行 item:align-content 可以移动多行组成的整体
Demo 3:align-content 控制的是行与行之间的空间
如果把 align-content 换成 space-between:
1 | .container { |
多行之间会被拉开。
注意:它不是把单个 item 拉开,而是在分配 flex line 之间的剩余空间。
align-content: space-between:分配多行之间的剩余空间
Demo 4:align-items 和 align-content 可以同时生效
多行场景里,这两个属性并不冲突。
比如:
1 | .container { |
这里会发生两件事:
align-content: center让多行整体在容器中居中。align-items: flex-start让每一行内部的 item 顶部对齐。
两者同时生效:align-content 管多行整体,align-items 管每一行里的 item
最容易记错的点
误区一:写了 flex-wrap,align-content 就会生效
不对。
flex-wrap: wrap 只是允许换行。
真正关键是有没有实际产生多行。
如果没有多行,align-content 没有控制对象。
误区二:align-content 是控制 item 垂直居中
不准确。
控制 item 的是 align-items。
控制多行整体分布的才是 align-content。
误区三:align-items 和 align-content 谁优先级更高
它们不是同一个维度的竞争关系。
align-items 看的是 item。
align-content 看的是 line。
当只有一行时,你通常只能看到 align-items 的效果。
当有多行时,它们可以同时生效。
最后总结
记住这个判断顺序:
- 我现在是不是 flex 容器?
- 主轴和交叉轴分别是什么方向?
- 我想控制的是 item,还是多行 line?
- 如果想用
align-content,是否真的产生了多行?
最终结论:
1 | align-items -> 控制 item |
所以你看到“align-content 不生效”的时候,第一反应应该是:
当前 flex 容器里,真的有多行吗?