简短回答
flex-wrap
属性看起来很基础——它控制弹性项目是否可以换行,但实际上它对整个弹性盒布局产生了广泛的影响。
flex-wrap
属性决定你将使用的弹性容器的类型。
flex-wrap: nowrap
创建一个单行弹性容器
flex-wrap: wrap
和wrap-reverse
创建一个多行弹性容器
align-items
和align-self
属性在单行和多行容器中均可使用。然而,它们只有在弹性线的交叉轴上有空闲空间时才能起作用。
align-content
属性仅在多行容器中起作用,在单行容器中被忽略。
解释
flexbox specification提供了四个关键字属性来对齐弹性项目:
align-items
align-self
align-content
justify-content
要理解这些属性的功能,首先需要了解弹性容器的结构。
第一部分:理解Flex容器的主轴和交叉轴
X轴和Y轴
Flex容器在两个方向上工作:x轴(水平)和y轴(垂直)。
![x-axis and the y-axis](https://istack.dev59.com/wmy0R.webp)
来源:维基百科
flex 容器的子元素,也称为“flex 项目”,可以在任何方向上对齐。(忽略上面图片中的 z 轴。这里不适用。)
这是 flex 对齐的最基本层次。
主轴和交叉轴
在 flex 布局中,覆盖 x 和 y 轴的是 主轴 和 交叉轴。
默认情况下,主轴是水平的(x 轴),交叉轴是垂直的(y 轴)。这是根据 flexbox 规范 定义的初始设置。
![flex main axis and cross axis](https://istack.dev59.com/9Oxw7.webp)
来源: W3C
然而,与固定的 x 和 y 轴不同,主轴和交叉轴可以交换方向。
flex-direction
属性
在上面的图像中,主轴是水平的,交叉轴是垂直的。如前所述,这是 flex 容器的初始设置。
然而,这些方向可以通过 flex-direction
属性轻松地进行切换。该属性控制主轴的方向;它确定 flex 项目是垂直还是水平对齐。
来自规范:
5.1. 弹性流方向:flex-direction属性
flex-direction
属性指定了弹性容器中的伸缩项如何放置,通过设置弹性容器主轴的方向来确定伸缩项的布局方向。
flex-direction
属性有四个值:
flex-direction: row;
flex-direction: row-reverse;
flex-direction: column;
flex-direction: column-reverse;
交叉轴始终与主轴垂直。
第二部分:弹性线
在容器内,弹性项存在于一条线上,称为“弹性线”。
弹性线可以是行或列,具体取决于flex-direction
属性。
一个容器可以有一个或多个弹性线,具体取决于flex-wrap
属性。
单行弹性容器
flex-wrap: nowrap
建立了一个单行弹性容器,在这个容器中,弹性项被强制保持在一行内(即使它们溢出容器)。
![a single-line flex container (one column)](https://istack.dev59.com/i4f2k.webp)
上面的图像有一条弹性线。
flex-container {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
width: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
多行弹性容器
flex-wrap: wrap
或 wrap-reverse
建立一个多行弹性容器,其中弹性项可以创建新的行。
![multi-line flex container (3 columns)](https://istack.dev59.com/UVKhz.webp)
上面的图片有三个弹性线。
flex-container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
width: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
![multi-line flex container (3 rows)](https://istack.dev59.com/kp4MO.webp)
上面的图片有三个弹性线。
flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
第三部分:关键词对齐属性
属性被分配给主轴和交叉轴(而不是X轴和Y轴)
虽然flex-direction
属性控制flex项目的布局方向,但有四个属性控制对齐和定位。它们是:
align-items
align-self
align-content
justify-content
每个属性都永久分配给一个轴。
justify-content
属性仅在主轴中起作用。
三个align-*
属性仅在交叉轴中起作用。
常见的错误是认为这些属性固定于x轴和y轴。例如,justify-content
总是水平的,而align-items
总是垂直的。
但是,当flex-direction
切换为column
时,主轴变成了y轴,justify-content
在垂直方向上起作用。
本文重点介绍交叉轴对齐。有关主轴对齐和
justify-content
属性的解释,请参见此文章:
定义
Flexbox规范提供了三个关键字属性用于交叉轴对齐:
align-items
align-self
align-content
align-items
/ align-self
align-items
属性沿着 flex 行的交叉轴对齐 flex 项。它适用于 flex 容器。
align-self
属性用于覆盖单个 flex 项上的 align-items
。它适用于 flex 项。
以下是规范中的定义:
8.3. 交叉轴对齐:align-items 和 align-self 属性
弹性项目可以在当前行的交叉轴上对齐,类似于 justify-content,但是在垂直方向上。align-items 设置所有弹性容器项目的默认对齐方式。align-self 允许单独的弹性项目覆盖此默认对齐方式。
align-items
/
align-self
有六个可能的值:
- flex-start
- flex-end
- center
- baseline
- stretch
- auto (仅适用于 align-self)
(点击上面的规范定义标题以获取每个值的描述。)
< p >
align-items
的初始值为
stretch
,意味着 flex 项目将扩展容器交叉轴上的整个可用长度。
align-self
的初始值为 auto
,这意味着它继承了 align-items
的值。
下面是在行方向容器中每个值的效果示例。
![align-items align-self values](https://istack.dev59.com/8A6EZ.webp)
来源: W3C
align-content
这个属性比align-items
和align-self
稍微复杂一些。
以下是规范中的定义:
8.4. 对齐弹性线: align-content
属性
当在交叉轴上有额外空间时,align-content
属性将弹性容器内的弹性线对齐到弹性容器内,类似于 justify-content
将单个项目对齐到主轴上。请注意,此属性不会影响单行弹性容器。
与align-items
和align-self
不同的是,它们移动弹性项目在其行内,align-content
则移动弹性线在容器内。
有六个可能的值可用于 align-content
:
flex-start
flex-end
center
space-between
space-around
stretch
(有关每个值的描述,请单击上面的规范定义标题。)
以下是在行方向容器中每个值的效果示例。
![enter image description here](https://istack.dev59.com/2HjlC.webp)
来源:W3C
为什么align-content
只在多行flex容器中起作用?
在单行flex容器中,行的交叉轴尺寸等于容器的交叉轴尺寸。这意味着行和容器之间没有空余空间。因此,align-content
无法发挥作用。
以下是规范中相关的部分:
只有多行flex容器才有交叉轴上的自由空间可以对齐行,因为在单行flex容器中,唯一的行会自动拉伸以填充空间。
第四部分:示例解释
![enter image description here](https://istack.dev59.com/E9uHd.webp)
在示例1中,
align-self
与
flex-wrap: nowrap
配合使用,因为 flex 项目存在于单行容器中。因此,只有一条 flex 行,它与容器的高度相匹配。
flex-container {
display: flex;
flex-wrap: nowrap;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:last-child {
align-self: flex-end;
background-color: crimson;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
![enter image description here](https://istack.dev59.com/3UtjN.webp)
在示例2中,
align-self
失败,因为它存在于多行容器(
flex-wrap:wrap
)中,并且
align-content
设置为
flex-start
。这意味着flex行紧密地打包到交叉轴的起点,没有留下任何自由空间供
align-self
使用。
flex-container {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:last-child {
align-self: flex-end;
background-color: crimson;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
![enter image description here](https://istack.dev59.com/Ijjxk.webp)
例子 #3 的解释与例子 #1 相同。
flex-container {
display: flex;
flex-wrap: nowrap;
align-items: flex-end;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
![enter image description here](https://istack.dev59.com/jEs73.webp)
例子4的解释与例子2相同。
flex-container {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
align-content: flex-start;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
![enter image description here](https://istack.dev59.com/1ydI0.webp)
示例#5是单行容器。因此,flex行的交叉尺寸等于容器的交叉尺寸,两者之间没有额外的空间。因此,align-content
在交叉轴上有额外空间时对齐flex行,但在此情况下无效。
flex-container {
display: flex;
flex-wrap: nowrap;
align-content: center;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
![enter image description here](https://istack.dev59.com/Kpy8P.webp)
align-content
的初始设置是
stretch
。这意味着如果没有指定其他值,容器将在伸缩行之间均匀分配可用空间。(当所有伸缩项都获得
flex: 1
时,在主轴上会产生类似的效果。)
此空间分配可能会导致行/列之间的宽间隙。较少的行会导致较宽的间隙。较多的行会导致较小的间隙,因为每个行会获得更小的空间份额。
要解决此问题,请从
align-content: stretch
切换到
align-content: flex-start
。这会将行紧密地排在一起 (参见上面的示例#2和#4)。当然,这也会消除行中的任何自由空间,且
align-items
和
align-self
不再起作用。
这是一个相关的帖子:
在伸缩项换行时去除它们之间的空格(间隙)
flex-container {
display: flex;
flex-wrap: wrap;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
![enter image description here](https://istack.dev59.com/tfKpo.webp)
如前面的例子所解释的那样,使用
align-content: stretch
,弹性行中可以有额外的空间,这使得
align-items
和
align-self
生效。任何其他
align-content
值都会打包行,消除额外的空间,使
align-items
和
align-self
无用。
flex-container {
display: flex;
flex-wrap: wrap;
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
flex-item:nth-child(even) {
align-self: flex-end;
background-color: crimson;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
justify-self
属性。不起作用。https://dev59.com/tlwY5IYBdhLWcg3wgX6V - Michael Benjamin