Flexbox 基础概念

弹性盒子布局 模块(通常称为 Flexbox)是一种用于在项目之间分配空间的一维布局模型,并包含许多对齐功能。本文概述了 Flexbox 的主要功能,我们将在这些指南的其余部分更详细地探讨这些功能。

当我们将 Flexbox 描述为一维时,我们指的是 Flexbox 一次处理一个维度上的布局——作为一行或一列。这与 CSS 网格布局 的二维模型形成对比,后者同时控制列和行。

Flexbox 的两个轴

使用 Flexbox 时,您需要考虑两个轴——主轴交叉轴主轴flex-direction 属性定义,而 交叉轴 则垂直于它。我们使用 Flexbox 所做的一切都参考这些轴,因此从一开始就了解它们的工作原理非常有价值。

主轴

主轴flex-direction 定义,它有四个可能的值

  • row
  • row-reverse
  • column
  • column-reverse

如果您选择 rowrow-reverse,则您的主轴将沿行的**内联方向**运行。

If flex-direction is set to row the main axis runs along the row in the inline direction.

选择 columncolumn-reverse,您的主轴将沿**块方向**运行,从页面顶部到底部。

If flex-direction is set to column the main axis runs in the block direction.

交叉轴

交叉轴 垂直于主轴。因此,如果您的 flex-direction(主轴)设置为 rowrow-reverse,则交叉轴沿列运行。

If flex-direction is set to row then the cross axis runs in the block direction.

如果您的主轴是 columncolumn-reverse,则交叉轴沿行运行。

If flex-direction is set to column then the cross axis runs in the inline direction.

起始行和结束行

另一个重要的理解领域是 Flexbox 对文档的书写模式不做任何假设。Flexbox 不仅仅假设所有文本行都从文档的左上角开始并向右侧运行,新行出现在另一行下方。相反,它支持所有书写模式,就像其他 逻辑属性和值 一样。

您可以在后面的文章中 阅读有关 Flexbox 和书写模式之间关系的更多信息;但是,以下描述应该有助于解释为什么我们在描述 Flex 项目的流动方向时不谈论左右和上下。

如果flex-direction属性的值为row,并且我使用的是英语,那么主轴的起始边将在左侧,结束边将在右侧。

Working in English the start edge is on the left.

如果我使用的是阿拉伯语,那么我的主轴的起始边将在右侧,结束边将在左侧。

The start edge in a RTL language is on the right.

在这两种情况下,交叉轴的起始边都在弹性容器的顶部,结束边都在底部,因为这两种语言都具有水平书写模式。

过一段时间后,思考起始和结束而不是左右会变得自然,并且在处理其他布局方法(例如遵循相同模式的CSS网格布局)时会对您有所帮助。

Flex 容器

使用弹性盒布局的文档区域称为**弹性容器**。要创建弹性容器,请将该区域的display属性设置为flex。当我们这样做时,该容器的直接子元素将成为**弹性项目**。您可以使用inline flexinline-flex显式控制容器本身是显示为内联还是块级格式化上下文(用于内联弹性容器),或者使用block flexflex(用于块级弹性容器)。

初始值

与CSS中的所有属性一样,定义了一些初始值,因此新弹性容器的内容将以以下方式表现

  • 项目以行显示(flex-direction属性的默认值为row)。
  • 项目从主轴的起始边开始。
  • 项目在主尺寸上不会拉伸,但可以收缩(弹性项目的flex-grow属性的默认值为0,其flex-shrink属性的默认值为1)。
  • 项目将拉伸以填充交叉轴的大小(align-items属性的默认值为stretch)。
  • 弹性项目的flex-basis属性的默认值为auto。这意味着在每种情况下,它都将等于弹性项目在水平书写模式下的width,以及在垂直书写模式下的弹性项目height。如果相应的width/height也设置为auto,则改为使用flex-basiscontent值。
  • 所有项目都将位于一行中(flex-wrap属性的默认值为nowrap),如果它们的组合width/height超过包含元素的width/height,则会溢出其容器。

其结果是,您的所有项目都将排成一行,使用内容的大小作为其在主轴上的大小。如果项目数量超过容器所能容纳的数量,它们不会换行,而是会溢出。如果某些项目比其他项目更高,则所有项目都将在交叉轴的整个长度上拉伸。

您可以在下面的实时示例中看到它的外观。尝试编辑项目或添加其他项目以测试弹性盒的初始行为。

更改flex-direction

flex-direction属性添加到弹性容器允许我们更改弹性项目显示的方向。设置flex-direction: row-reverse将使项目沿行显示,但是起始线和结束线将被切换。

如果我们将flex-direction更改为column,则主轴会切换,我们的项目现在会以列的形式显示。设置column-reverse,起始线和结束线将再次被切换。

下面的实时示例将flex-direction设置为row-reverse。尝试其他值 - rowcolumncolumn-reverse - 以查看内容发生了什么变化。

使用 flex-wrap 的多行 Flex 容器

虽然弹性盒是一维模型,但可以使弹性项目跨多行换行。如果这样做,您应该将每一行视为一个新的弹性容器。任何空间分配都将在每一行中进行,而不参考前一行或后续行。

要导致换行行为,请添加属性flex-wrap,其值为wrap。现在,如果您的项目太大而无法在一行中全部显示,它们将换行到另一行。下面的实时示例包含已设置width的项目。项目的总宽度对于弹性容器来说太宽了。由于flex-wrap设置为wrap,因此项目跨多行换行。如果将其设置为nowrap(初始值),它们将缩小以适应容器。它们会缩小,因为它们使用的是初始弹性盒值,包括flex-shrink: 1,这允许项目缩小。如果项目无法缩小,或者无法缩小到足以适应容器的大小,则使用nowrap会导致溢出

在指南掌握弹性项目的换行中了解有关换行弹性项目的更多信息。

flex-flow 简写

您可以将两个属性flex-directionflex-wrap组合到flex-flow简写中。

在下面的实时示例中,尝试将第一个值更改为flex-direction允许的值之一 - rowrow-reversecolumncolumn-reverse,并将第二个值更改为wrapnowrap

应用于 Flex 项目的属性

要控制每个弹性项目的大小,我们通过三个属性直接定位它们

我们将在下面简要介绍这些属性,但是如果您需要更全面的信息,请查看控制弹性项目在主轴上的比例指南。

在我们理解这些属性之前,我们需要考虑**可用空间**的概念。当我们更改这些弹性属性的值时,我们所做的是更改可用空间在我们项目中的分配方式。当我们开始对齐项目时,可用空间的概念也很重要。

如果我们在宽度为500像素的容器中有三个宽度为100像素的项目,那么我们布置这些项目所需的空间为300像素。这留下了200像素的可用空间。如果我们不更改初始值,则弹性盒会将该空间放在最后一个项目之后。

This flex container has available space after laying out the items.

如果我们希望项目增长并填充空间,那么我们需要有一种方法在项目之间分配剩余的空间。我们应用于项目本身的flex属性使我们能够指示如何将该可用空间分配给同级弹性项目。

flex-basis属性

flex-basis定义了该项目在可用空间方面的大小。此属性的初始值为auto - 在这种情况下,浏览器会查看项目是否具有大小。在上面的示例中,所有项目的宽度都为100像素。这用作flex-basis

如果项目没有大小,则内容的大小将用作flex-basis。这就是为什么当我们只是在父元素上声明display: flex来创建弹性项目时,所有项目都会移到一行并只占用显示其内容所需的尽可能小的空间。

flex-grow属性

如果flex-grow属性设置为正整数,并且有可用空间,则弹性项目可以沿主轴从其flex-basis增长。项目是否拉伸以占用该轴上的所有可用空间,或者只是部分可用空间,取决于其他项目是否也允许增长以及其flex-grow属性的值。

每个具有正值的项目都会根据其flex-grow值消耗一部分可用空间。如果我们在上面的示例中为所有项目都提供flex-grow值为1,则弹性容器中的可用空间将在我们的项目之间平均分配,并且它们将拉伸以填充主轴上的容器。如果我们给第一个项目一个flex-grow值为2,而其他项目每个值为1,则总共有4个部分;可用空间的2个部分将分配给第一个项目(在上面的示例中,为200像素中的100像素),其他两个项目每个部分为1(在总共200像素中,每个为50像素)。

flex-shrink属性

flex-grow属性用于在主轴上添加空间,而flex-shrink属性控制如何将其移除。如果我们没有足够的空间在容器中布置我们的项目,并且flex-shrink设置为正整数,则该项目可以小于flex-basis。与flex-grow一样,可以分配不同的值以导致一个项目比其他项目收缩得更快 - 为flex-shrink设置较高值的项目将比其具有较低值的同级项目收缩得更快。

项目可以缩小到其min-content大小。在计算将发生的实际收缩量时,会考虑此最小大小,这意味着flex-shrink的行为可能不如flex-grow一致。因此,我们将在文章控制项目在主轴上的比例中更详细地了解此算法的工作原理。

注意:flex-growflex-shrink的这些值是比例。通常,如果我们将所有项目的设置为flex: 1 1 200px,然后希望一个项目以两倍的速度增长,我们将把该项目设置为flex: 2 1 200px。但是,如果您愿意,也可以使用flex: 10 1 200pxflex: 20 1 200px

flex属性的简写值

您很少会看到flex-growflex-shrinkflex-basis属性单独使用;相反,它们被组合到flex简写中。flex简写允许您按此顺序设置三个值 - flex-growflex-shrinkflex-basis

下面的实时示例允许您测试flex简写的不同值;请记住,第一个值是flex-grow。赋予它一个正值意味着该项目可以增长。第二个是flex-shrink - 具有正值,项目可以缩小,但前提是它们的总值溢出了主轴。最后一个值是flex-basis;这是项目用作其基本值以增长和缩小的值。

还有一些预定义的简写值涵盖了大多数用例。您经常会在教程中看到这些值,并且在许多情况下,这些值是您唯一需要使用的。预定义的值如下

  • flex: initial
  • flex: auto
  • flex: none
  • flex: <positive-number>

initial值是CSS全局值,它表示属性的初始值。设置flex: initial会将项目重置为三个详细属性的初始值,这与flex: 0 1 auto相同。flex-grow的初始值为0,因此项目不会增长到超过其flex-basis大小。flex-shrink的初始值为1,因此项目如果需要可以收缩,而不是溢出。flex-basis的初始值为auto。项目将使用在主尺寸上为项目设置的任何大小,或者它们将从内容大小获取其大小。

使用flex: auto与使用flex: 1 1 auto效果相同;这类似于flex: initial,区别在于项目可以增长并填充容器,并在需要时收缩。

使用flex: none将创建完全不可伸缩的弹性项目。这就像你写了flex: 0 0 auto一样。项目不能增长或收缩,并且将使用弹性盒布局和flex-basis值为auto进行排列。

你在教程中经常看到的简写是flex: 1flex: 2等等。这分别等同于写flex: 1 1 0flex: 2 1 0。项目可以从flex-basis值为0开始增长和收缩。

在下面的实时示例中尝试这些简写值。

项目之间的对齐、对齐方式和空闲空间分配

弹性盒的一个关键特性是能够在主轴和交叉轴上对齐和对正项目,以及在弹性项目之间分配空间。请注意,这些属性设置在弹性容器上,而不是在项目本身上。

align-items

align-items属性在交叉轴上对齐所有弹性项目。

此属性的初始值为stretch,这也是弹性项目默认情况下会拉伸到弹性容器高度的原因(如果flex-direction设置为columncolumn-reverse,则为宽度)。此高度可能来自容器中最高的项目,也可能来自弹性容器本身设置的大小。

你可以将align-items设置为flex-start或简写为start,以使项目在弹性容器的起始处对齐,设置为flex-end或简写为end,以将其对齐到末尾,或设置为center以将其对齐到中心。在实时示例中尝试一下——我已经为弹性容器设置了一个高度,以便你可以看到项目如何在容器内移动。看看如果你将align-items的值设置为以下值会发生什么情况:

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

align-items设置在弹性容器上,并影响所有弹性项目。如果你想将某个弹性项目与其他项目对齐方式不同,可以在弹性项目上设置align-self

justify-content

justify-content属性用于在主轴上对齐项目,即flex-direction设置流的方向。初始值为flex-start,它将项目在容器的起始边缘对齐,但你也可以将其值设置为flex-end以将其对齐到末尾,或设置为center以将其对齐到中心。

你还可以使用space-between值来获取项目布局后所有剩余的空间,并在项目之间平均分配这些空间,这样每个项目之间都会有相等的空间。要使每个项目的右侧和左侧(或列的顶部和底部)有相等的空间,请使用space-around值。使用space-around,项目两端会有一个半尺寸的空间。或者,要使项目周围有相等的空间,请使用space-evenly值。使用space-evenly,项目两端会有一个全尺寸的空间。

在实时示例中尝试以下justify-content值:

  • start
  • end
  • left
  • right
  • normal
  • flex-start
  • flex-end
  • center
  • space-around
  • space-between
  • space-evenly
  • stretch

文章Aligning items in a flex container更深入地探讨了这些属性,以便更好地理解它们的工作原理。但是,这些基本示例在大多数用例中都很有用。

justify-items

justify-items属性在弹性盒布局中被忽略。

place-items 和 place-content

place-items属性是align-itemsjustify-items的简写属性。如果设置在弹性容器上,它将设置对齐方式但不设置对正方式,并且justify-items在弹性盒中被忽略。

还有一个简写属性place-content,它定义了align-contentjustify-content属性。align-content属性仅影响换行的弹性容器,并在Aligning items in a flex container中进行了讨论。

后续步骤

阅读本文后,你应该了解弹性盒的基本功能。在下一篇文章中,我们将了解此规范与 CSS 的其他部分的关系