flex-wrap如何使用align-self,align-items和align-content?

Mic*_*l_B 56 css css3 flexbox

align-self

在以下代码中,align-self使用flex-wrap: nowrap.

在此输入图像描述

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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

但是当容器切换到时flex-wrap: wrap,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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


align-items

同样,为什么在align-items这里工作(包括禁用):

在此输入图像描述

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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

...但不在这里(启用换行):

在此输入图像描述

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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


align-content

使用时flex-wrap: nowrap,该align-content属性不会垂直居中灵活项目:

在此输入图像描述

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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

但是,奇怪的是,如果启用了wrap并将align-content其省略,则容器会在行之间创建大的间隙:

在此输入图像描述

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

align-self再次工作.

在此输入图像描述

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

如何flex-wrap使用align-self,align-itemsalign-content?

Mic*_*l_B 101

Short Answer

Although the flex-wrap property seems pretty basic – it controls whether flex items can wrap – it actually has a wide-ranging impact on the entire flexbox layout.

The flex-wrap property determines the type of flex container you will use.

  • flex-wrap: nowrap creates a single-line flex container
  • flex-wrap: wrap and wrap-reverse create a multi-line flex container

The align-items and align-self properties work in both single- and multi-line containers. However, they can only have an effect when there's free space in the cross axis of the flex line.

The align-content property works only in multi-line containers. It is ignored in single-line containers.


Explanation

The flexbox specification provides four keyword properties for aligning flex items:

  • align-items
  • align-self
  • align-content
  • justify-content

To understand the functions of these properties it's important to first understand the structure of a flex container.


Part 1: Understanding the Main Axis and Cross Axis of a Flex Container

The X and Y Axes

A flex container works in two directions: x-axis (horizontal) and y-axis (vertical).

x轴和y轴

                                                                                                                Source: Wikipedia

The child elements of a flex container – known as "flex items" – can be aligned in either direction.

This is flex alignment at its most fundamental level.

The Main and Cross Axes

Overlaying the x and y axes are, in flex layout, the main and cross axes.

By default, the main axis is horizontal (x-axis), and the cross axis is vertical (y-axis). That's the initial setting, as defined by the flexbox specification.

弯曲主轴和横轴

                                                                                                                Source: W3C

However, unlike the x and y axes, which are fixed, the main and cross axes can switch directions.

The flex-direction Property

In the image above, the main axis is horizontal and the cross axis is vertical. As mentioned earlier, that's an initial setting of a flex container.

However, these directions can be easily switched with the flex-direction property. This property controls the direction of the main axis; it determines whether flex items align vertically or horizontally.

From the spec:

5.1. Flex Flow Direction: the flex-direction property

The flex-direction property specifies how flex items are placed in the flex container, by setting the direction of the flex container’s main axis. This determines the direction in which flex items are laid out.

flex-direction属性有四个值:

/* main axis is horizontal, cross axis is vertical */
flex-direction: row; /* default */
flex-direction: row-reverse;

/* main axis is vertical, cross axis is horizontal */    
flex-direction: column;
flex-direction: column-reverse;
Run Code Online (Sandbox Code Playgroud)

横轴始终垂直于主轴.


第2部分:弹性线

在容器内,flex项存在于一条线中,称为"flex line".

弹性线是行或列,具体取决于flex-direction.

容器可以有一行或多行,具体取决于flex-wrap.

单线Flex容器

flex-wrap: nowrap 建立一个单行的flex容器,其中flex项目被强制保留在一行中(即使它们溢出容器).

单线柔性容器(一列)

上图有一条柔性线.

flex-container {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap; /* <-- allows single-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  width: 50px;
  margin: 5px;
  background-color: lightgreen;
}
Run Code Online (Sandbox Code Playgroud)
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>
Run Code Online (Sandbox Code Playgroud)

多线Flex容器

flex-wrap: wrapwrap-reverse建立多行灵活容器,其中弹性项可以创建新行.

多线柔性容器(3列)

上图有三条柔性线.

flex-container {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap; /* <-- allows multi-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  width: 50px;
  margin: 5px;
  background-color: lightgreen;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

多线柔性容器(3排)

上图有三条柔性线.

flex-container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap; /* <-- allows multi-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


第3部分:关键字对齐属性

属性分配给主轴和交叉轴(非X轴和Y轴)

While the flex-direction property controls the direction in which flex items are laid out, there are four properties that control alignment and positioning. These are:

  • align-items
  • align-self
  • align-content
  • justify-content

Each one of these properties is permanently assigned to an axis.

The justify-content property works only in the main axis.

The three align-* properties work only in the cross axis.

It's a common mistake to assume that these properties are fixed to the x and y axes. For example, justify-content is always horizontal, and align-items is always vertical.

However, when flex-direction is switched to column, the main axis becomes the y-axis, and justify-content works vertically.

The focus of this post is cross-axis alignment. For an explanation of main-axis alignment and the justify-content property, see this post:

Definitions

The flexbox specification provides three keyword properties for cross-axis alignment:

  • align-items
  • align-self
  • align-content

align-items/align-self

The align-items property aligns flex items along the cross axis of the flex line. It applies to flex containers.

The align-self property is used to override align-items on individual flex items. It applies to flex items.

Here's the definition from the spec:

8.3. Cross-axis Alignment: the align-items and align-self properties

Flex items can be aligned in the cross axis of the current line of the flex container, similar to justify-content but in the perpendicular direction. align-items sets the default alignment for all of the flex container’s items. align-self allows this default alignment to be overridden for individual flex items.

There are six possible values for align-items/align-self:

  • flex-start
  • flex-end
  • center
  • baseline
  • stretch
  • auto (align-self only)

(For a description of each value, click on the spec definition heading above.)

The initial value of align-items is stretch, meaning flex items will expand the full available length of the container's cross axis.

The initial value of align-self is auto, meaning it inherits the value of align-items.

Below is an illustration of the effect of each value in a row-direction container.

align-items align-self values

                                                                                                                source: W3C

align-content

This property is slightly more complex than align-items and align-self.

Here's the definition from the spec:

8.4. Packing Flex Lines: the align-content property

The align-content property aligns a flex container’s lines within the flex container when there is extra space in the cross-axis, similar to how justify-content aligns individual items within the main-axis. Note, this property has no effect on a single-line flex container.

In contrast to align-items and align-self, which move flex items within their line, align-content moves flex lines within the container.

There are the six possible values for align-content:

  • flex-start
  • flex-end
  • center
  • space-between
  • space-around
  • stretch

(For a description of each value, click on the spec definition heading above.)

Below is an illustration of the effect of each value in a row-direction container.

enter image description here

                                                                                                                source: W3C

Why does align-content work only in multi-line flex containers?

In a single-line flex container, the cross size of the line is equal to the cross size of the container. This means there is no free space between the line and the container. As a result, align-content can have no effect.

Here's the relevant section from the spec:

Only multi-line flex containers ever have free space in the cross-axis for lines to be aligned in, because in a single-line flex container the sole line automatically stretches to fill the space.


Part 4: Examples Explained

enter image description here

In Example #1, align-self works with flex-wrap: nowrap because the flex items exist in a single-line container. Therefore, there is one flex line and it matches the height of the container.

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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

enter image description here

In Example #2, align-self fails because it exists in a multi-line container (flex-wrap: wrap) and align-content is set to flex-start. This means that flex lines are packed tightly to the start of the cross axis, leaving no free space for align-self to work.

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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

enter image description here

The explanation for Example #3 is the same as for Example #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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

enter image description here

The explanation for Example #4 is the same as for Example #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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

enter image description here

Example #5 is a single-line container. As such, the cross size of the flex line equals the cross size of the container, leaving no extra space between the two. Therefore, align-content, which aligns flex lines when there is extra space in the cross axis, is having no effect.

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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

enter image description here

The initial setting for align-content is stretch. This means that if no other value is specified, the container will distribute available space evenly among flex lines. (A similar effect is created on the main axis when all flex items get flex: 1.)

This distribution of space among lines can cause wide gaps between rows/columns. Less lines result in wider gaps. More lines result in smaller gaps, as each line gets a smaller share of the space.

要解决此问题,请切换align-content: stretchalign-content: flex-start.这将线包装在一起(参见上面的例子#2和#4).当然,这也消除了线路上的任何可用空间,align-items并且align-self可以不再起作用.

这是一个相关的帖子:当它们换行时,删除多行flex项之间的空间(间隙)

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

enter image description here

如前面的示例中所解释的那样,align-content: stretch在柔性线中可以存在额外的空间,这允许align-itemsalign-self工作.任何其他值align-content都会包装线条,消除额外空间,制作align-itemsalign-self无用.

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

  • 对齐内容的良好解释:align-content属性修改了flex-wrap属性的行为.它与align-items类似,但它不是对齐flex项,而是对齐flex线. (3认同)
  • 这个答案应该转发给每个关于`align-items`和`align-content`的SO问题.开个玩笑,非常好的回答. (2认同)
  • 在开始学习flex然后理解它之后,最后发现chrome在移动设备上的表现不同,我放弃了,现在我后悔我会成为火箭科学家,哈哈 (2认同)

val*_*als 6

首先,如果没有 wrap, align-content 是没有用的:

w3c 文档

当横轴上有额外空间时,align-content 属性在 flex 容器内对齐 flex 容器的行,类似于 justify-content 在主轴内对齐单个项目的方式。请注意,此属性对单行 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-item:nth-child(5) {
  height: 90px;  /* added */
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

同样,在您的第四个示例中,如果您设置可以看到的条件,则样式正在起作用

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-item:nth-child(2),flex-item:nth-child(5) {
  height: 90px;  /* added */
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

最后,当您评论 align-content 时,它会恢复为stretch,这就是为什么线条会增加大小以填满容器

伸展线伸展以占用剩余空间。如果剩余可用空间为负,则该值与 flex-start 相同。否则,自由空间会在所有行之间平均分配,从而增加它们的交叉大小。

  • 关于第一句话,可能最好说*如果没有换行,就只有一行,然后align-content就没有用了*。我不太擅长用英语解释事情...... (3认同)