Flexbox

CSS 播客 - 第 10 集:Flexbox

在自适应设计中,边栏与某些内容内嵌在一起是一种比较棘手的设计模式。在视口空间充裕的情况下,这种模式非常适用,但在空间较为紧凑的情况下,这种刚性布局可能会出现问题。

灵活框布局模型 (flexbox) 是专为一维内容设计的布局模型。 它擅长处理大量不同尺寸的物品 并返回这些项的最佳布局。

这是此边栏模式的理想布局模型。Flexbox 不仅能以内嵌方式放置边栏和内容, 但若没有足够的剩余空间,边栏便会另起一行。 与其为浏览器设置固定的尺寸,不如 使用 Flexbox 则可以改为提供灵活的边界来提示内容可以如何展示。

您可以使用 Flex 布局执行哪些操作?

Flex 布局具有以下特性, 我们将在本指南中介绍相关内容

  • 它们可以显示为行,也可以显示为列。
  • 它们遵循文档的书写模式。
  • 它们默认是单行,但可以要求换行显示。
  • 布局中的项可以视觉上重新排序,而与 DOM 中的顺序无关。
  • 空间可在项中分配,以便它们根据父项中可用的空间而变大变小。
  • 空间可以分布在封装布局中的项和 Flex 行周围, 使用文本框对齐方式属性
  • 这些项本身可以在交叉轴上对齐。

主轴和交叉轴

了解 Flexbox 的关键在于了解主轴和交叉轴的概念。 主轴是您的 flex-direction 属性设置的主轴。 如果该值为 row,则主轴沿行;如果该值为 column,则主轴沿列。

三个并排的框,其中有一个箭头,指向左到右。箭头标示为“主轴”

Flex 项作为一个组在主轴上移动。 请记住:我们有很多内容,正在努力为小组成员提供最佳布局。

交叉轴与主轴相反,因此如果 flex-directionrow,交叉轴将沿列运行。

三个不同高度的框并排排列,中间有一个箭头,指向左到右。箭头标记为主轴。还有一个箭头从上向下指向。这个图表标记为“交叉轴”

您可以在交叉轴上执行两项操作。您可以单独或成组移动这些项,以便它们彼此对齐并与 Flex 容器对齐。此外,如果使用了封装在一起的弹性行 您可以将这些行视为一组,以控制为这些行分配空间的方式。 在本指南中,您将了解这一切的实际运作方式。 现在只需注意,主轴跟随 flex-direction

创建 flex 容器

我们来看看 Flexbox 的行为方式,为此,我们将一组不同大小的项取出,并使用 Flexbox 对其进行布局。

<div class="container" id="container">
  <div>One</div>
  <div>Item two</div>
  <div>The item we will refer to as three</div>
</div>

如需使用 Flexbox,您需要声明要使用 Flex 格式上下文,而不是常规的块级和内嵌布局。为此,请将 display 属性的值更改为 flex

.container {
  display: flex;
}

如您在布局指南中所学,这将为您提供一个包含 flex 项子项的块级盒子。Flex 项会根据其初始值立即开始表现出某些 Flexbox 行为。

初始值表示:

  • 各项内容会显示为一行。
  • 它们不会换行。
  • 它们不会变大来填满容器。
  • 它们在容器的开头处对齐。

控制项的方向

即使您尚未添加 flex-direction 属性,这些项也会显示为一行,因为 flex-direction 的初始值为 row。如果您只需要添加一行,则无需添加相应属性。 如需更改方向,请添加该属性和以下四个值之一:

  • row:项排列成行。
  • row-reverse:,这些项从 flex 容器末尾排列为一行。
  • column:项以列的形式排列。
  • column-reverse:这些项从 flex 容器末尾排列为一列。

您可以通过以下演示中的项目组尝试所有值。

反转项和无障碍功能的流程

使用任何会使视觉显示顺序与 HTML 文档中的顺序不一致的属性时,都应谨慎小心,因为这可能会对无障碍功能产生负面影响。row-reversecolumn-reverse 值就是一个很好的示例。 重新排序仅适用于视觉顺序,而非逻辑顺序。请务必了解这一点,因为逻辑顺序是屏幕阅读器读出内容的顺序,也是使用键盘导航的用户遵循的顺序。

您可以在以下视频中了解,在反向行布局中,由于键盘导航会遵循 DOM 而非视觉显示,因此在链接之间按 Tab 键时会断开连接。

任何能够更改 Flexbox 或网格中项顺序的内容都可能会导致此问题。 因此,任何重新排序都应包括全面的测试,确保网站不会 对某些人来说很难使用。

如需了解详情,请参阅以下内容:

写入模式和方向

默认情况下,Flex 项以行布局。 行是按照写作模式和脚本方向流动的句子的方向排列的。这意味着,如果您使用的是阿拉伯语(采用从右到左 [rtl] 的脚本方向),则项目将在右侧对齐。制表符顺序也会从右侧开始,因为这是阿拉伯语朗读句子的方式。

如果您使用的是竖向书写模式, 就会有一行从上到下垂直排列 尝试更改此演示中使用纵向书写模式的 flex-direction

因此,Flex 项的默认行为方式与文档的写入模式相关联。 大多数教程都是使用英语或其他横向从左到右的书写模式编写的。这样就很容易假设弹性项排在左侧,并且是水平运行。

根据主轴和横轴以及书写模式, 事实上,在上述示例中我们谈论的是 startend,而不是顶部、底部、左侧和右侧。 那么 Flexbox 可能更易于理解。 每个轴都有起点和终点。 主轴的起点称为 main-start。因此,我们的 Flex 项最初会从 main-start 对齐。该轴的端点是 main-end。交叉轴的起点为 cross-start,终点为 cross-end

上述术语的带标签图

换行 flex 项

flex-wrap 属性的初始值为 nowrap。 这意味着,如果容器中没有足够的空间,这些项就会溢出。

一个包含九个项的 Flex 容器,这些项已缩小,因此一个字词在一行中,但没有足够的空间并排显示这些项,因此 Flex 项已延伸到容器的边框之外。
一旦达到内容大小下限,Flex 项目就会开始溢出其容器

使用初始值显示的项目会尽可能缩小, 缩减至 min-content 大小后才会发生溢出。

如需使项封装,请向 flex 容器添加 flex-wrap: wrap

.container {
  display: flex;
  flex-wrap: wrap;
}

当 Flex 容器换行时,它会创建多个 Flex 行。在空间分配方面,每行都像一个新的 Flex 容器。因此,如果要对行进行封装 第 2 行中的内容不可能与第 1 行中其上的内容对齐。 这就是 flexbox 是一维的意思。 您可以控制一个轴(行或列)中的对齐方式,但不能同时控制这两个轴(就像在网格中一样)。

Flex-flow 简写形式

您可以使用简写形式 flex-flow 设置 flex-directionflex-wrap 属性。 例如,如需将 flex-direction 设置为 column 并允许内容换行,请使用以下代码:

.container {
  display: flex;
  flex-flow: column wrap;
}

控制 Flex 项内的间距

假设容器的空间超出了显示列表项所需的空间, 这些项在开始时排成一行,并且不会变大以填满空间。 它们不会再达到内容大小上限。 这是因为 flex- 属性的初始值为:

  • flex-grow: 0:内容不会增长。
  • flex-shrink: 1:项可以缩小到小于其 flex-basis 的尺寸。
  • flex-basis: auto:项目的基本大小为 auto

可以用 flex: initial 的关键字值表示。 flex 简写属性, 或者 flex-growflex-shrinkflex-basis 的长手应用于 Flex 容器。

要使这些项变大 同时允许大型内容比小型内容拥有更多空间,请使用 flex:auto。 您可以使用上面的演示进行尝试。 这会将属性设为:

  • flex-grow: 1:内容可以大于其 flex-basis
  • flex-shrink: 1:项可以缩小到其 flex-basis 以下。
  • flex-basis: auto:项的基本大小为 auto

使用 flex: auto 意味着项最终会采用不同的大小,因为各个项之间共享的空间是在每个项以最大内容大小进行布局共享的。因此大型内容将会占据更多空间。 如需强制所有项保持一致的大小并忽略内容大小的变化,请在演示中将 flex:auto 更改为 flex: 1

这会解压缩到:

  • flex-grow: 1:内容可以大于其 flex-basis
  • flex-shrink: 1:项可以缩小到其 flex-basis 以下。
  • flex-basis: 0:项的基准大小为 0

使用 flex: 1 表示所有项的大小都为零, 因此 Flex 容器中的所有空间都可以进行分配。 由于所有项的 flex-grow 系数为 1,因此它们的增长率相同且空间均等。

允许项以不同的速率增长

您不必为所有项都设置 1flex-grow 系数。您可以为 Flex 项指定不同的 flex-grow 系数。在下面的演示中,第一项具有 flex: 1、第二个 flex: 2 和第三个 flex: 3。 随着这些项从 0 开始增长,Flex 容器中的可用空间会被分成 6 份。第一个项获得 1 份,第二个项获得 2 份,第三个项获得 3 份。

您也可以通过 autoflex-basis 执行相同的操作,不过您需要指定三个值。第一个值为 flex-grow,第二个值为 flex-shrink,第三个值为 flex-basis

.item1 {
  flex: 1 1 auto;
}

.item2 {
  flex: 2 1 auto;
}

这是一种不太常见的用例,因为使用 autoflex-basis 是为了让浏览器能够确定空间分布。如果您希望让某个项的增长幅度超出算法确定的幅度,那么它可能是 实用。

对 Flex 项重新排序

可以使用 order 属性对 Flex 容器中的项进行重新排序。 此属性允许对序数组中的项进行排序。项会按 flex-direction 指定的方向排列,值越低越先排列。如果多个项目具有相同的值,则该应用将与具有该值的其他项目一起显示。

以下示例演示了这种排序。

检查您的理解情况

测试您对 Flexbox 相关知识的掌握情况

flex-direction 的默认值为

row
默认情况下,Flexbox 会将内容放入一行,并在开头将它们排成一行。开启封装功能后,系统会继续创建可供子项在其中流动的行。
column
将 flex-direction 设置为 column 是堆叠元素的好方法,但这不是默认值。

默认情况下,Flex 容器会封装子项。

true
必须启用封装。
false
flex-wrap: wrapdisplay: flex 搭配使用以封装子项

Flex 子项显示为挤压,下面哪个 Flex 属性有助于缓解这种情况?

flex-grow
此属性描述元素是否可以超出基础大小,而不是它在基础下的行为方式。
flex-shrink
可以,此属性说明了在宽度低于基准时如何处理尺寸。
flex-basis
这提供了尺寸调整的起点,但并未说明如何处理宽度低于基准的尺寸调整场景(例如在压缩场景中)。

Flexbox 对齐概览

Flexbox 自带一组属性,可用于对齐项目和分配项目之间的空间。 这些属性非常实用,后来将它们转移到了他们自己的规范中, 您也会在“网格布局”中遇到它们。 您可在此处了解在使用 Flexbox 时它们是如何运作的。

这组房源可以分为两组。用于分配空间的属性和用于对齐的属性。 分布空间的属性包括:

  • justify-content:主轴上的空间分布。
  • align-content:横轴上的空间分布。
  • place-content:用于设置上述两个属性的简写形式。

Flexbox 中用于对齐的属性:

  • align-self:在横轴上对齐单个项。
  • align-items:在交叉轴上将所有项作为一个组对齐。

如果您处理主轴,则属性以 justify- 开头。 在交叉轴上,它们以 align- 开头。

在主轴上分配空间

在前面使用的 HTML 中,Flex 项排列成一行,因此主轴上有足够的空间。 项的大小不足以完全填满 flex 容器。 这些项会在 Flex 容器的开头排列,因为 justify-content 的初始值 为 flex-start。 项会在开头对齐,多余的空格会在结尾。

justify-content 属性添加到 Flex 容器中, 将其值设为flex-end 物品在容器末端排列,腾出空间放在起始位置。

.container {
  display: flex;
  justify-content: flex-end;
}

您还可以使用 justify-content: space-between 在项之间分配空间。

请尝试在演示中使用一些值,并参阅 MDN 了解完整的可能值集。

活动门票提供商:flex-direction: column

如果您已将 flex-direction 更改为 column,那么 justify-content 将可以继续正常使用 。 若要让容器在作为列时有空余空间,您需要为容器提供 heightblock-size。否则,您将没有多余的空间可供分发。

这次使用 Flexbox 列布局,尝试不同的值。

在 flex 行之间分配空间

使用经过封装的 flex 容器,您或许可以在交叉轴上分配空间。在这种情况下,您可以使用与 justify-content 相同的值 align-content 属性。 与默认将项对齐到 flex-startjustify-content 不同, align-content 的初始值为 stretch。 将 align-content 属性添加到 flex 容器,以更改此默认行为。

.container {
  align-content: center;
}

请在演示中试用此功能。 该示例包含换行 Flex 项,并且容器包含 block-size,以便我们留出一些空白。

place-content 简写形式

如需同时设置 justify-contentalign-content,您可以将 place-content 与一个或两个值搭配使用。如果您同时指定这两个值,则第一个值用于 align-content,第二个值用于 justify-content,这两个轴将使用相同的值。

.container {
  place-content: space-between;
  /* sets both to space-between */
}

.container {
  place-content: center flex-end;
  /* wrapped lines on the cross axis are centered,
  on the main axis items are aligned to the end of the flex container */
}

对齐交叉轴上的项

在交叉轴上,您还可以使用 align-items 对齐弹性线条中的项 和 align-self。 可用于此对齐方式的空间取决于 Flex 容器的高度,或者在内容已换行的情况下,取决于 Flex 行。

align-self 的初始值为 stretch,因此,默认情况下,一行中的 flex 项会延伸到最高项的高度。如需更改此设置,请向任意 Flex 项添加 align-self 属性。

.container {
  display: flex;
}

.item1 {
  align-self: flex-start;
}

使用以下任一值来对齐项:

  • flex-start
  • flex-end
  • center
  • stretch
  • baseline

请参阅 MDN 上的完整值列表

下一个演示包含一行包含 flex-direction: row 的 flex 项。最后一项定义 Flex 容器的高度。 第一个项的 align-self 属性值为 flex-start。尝试更改该属性的值,看看它在交叉轴上的空间内是如何移动的。

align-self 属性会应用于各个项。align-items 属性可应用于 Flex 容器,以将所有单独的 align-self 属性设置为一个组。

.container {
  display: flex;
  align-items: flex-start;
}

在下一个演示中,尝试更改 align-items 的值,以便将交叉轴上的所有项作为一组对齐。

为什么 Flexbox 中没有“ Justify-self”?

Flex 项在主轴上作为一个组。 因此,没有从该组中拆分个别项的概念。

在网格布局中,justify-selfjustify-items 属性会在内嵌轴上运行,以便在网格区域内对该轴上的项进行对齐。由于 Flex 布局将项视为组,因此这些属性不会在 Flex 上下文中实现。

值得注意的是,flexbox 确实可以与自动边距搭配使用。如果您需要将某个项目从组中拆分出来,或者将组拆分为两个组,可以应用边距来实现此目的。在以下示例中,最后一个项的左边距为 auto。自动外边距会吸收应用方向上的所有空间。 这意味着,它会将项推向右侧,从而拆分组。

如何垂直和水平居中显示内容

对齐方式属性可用于将某个项居中放置在另一个框内。 justify-content 属性将项在主轴上对齐, 也就是第 1 行。交叉轴上的 align-items 属性。

.container {
  width: 400px;
  height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
}

检查您的理解情况

测试您对 Flexbox 相关知识的掌握情况

.container {
  display: flex;
  direction: ltr;
}

要与 Flexbox 垂直对齐,请使用

对齐关键字
不错
对关键字进行排版
抱歉
.container {
  display: flex;
  direction: ltr;
}

要与 Flexbox 水平对齐,请使用

对齐关键字
抱歉
两全其美
不错
.container {
  display: flex;
  direction: ltr;
}

默认情况下,Flex 项会对齐到 stretch。想要内容 尺寸,您会使用以下哪种样式?

justify-content: flex-start
Justify 属性用于水平对齐,而不是垂直。
align-content: start
content 会对齐 Flex 行,而不是对齐子项。
height: auto
这不会产生任何影响。
align-items: flex-start
是,我们希望垂直地将它们与“顶部”对齐或 start,后者将移除默认的拉伸值,改为使用内容高度。

资源