Logo

弹性项目属性

了解弹性项目的排序、伸缩、基础尺寸和单独对齐属性

概念

弹性项目属性

了解弹性项目的排序、伸缩、基础尺寸和单独对齐属性

我们已经了解了弹性容器及其对齐属性。

确实非常美观。

你已经开始感受到接下来要学习的内容了。

现在,我建议暂时放下弹性容器,转而带你深入了解弹性项目及其对齐属性。

与弹性容器类似,一些对齐属性也适用于所有弹性项目。

让我为你逐一讲解。



1. Order(顺序)

order 属性允许重新排列容器内的弹性项目。

简单来说,通过 order 属性,你可以将某个弹性项目从一个位置移动到另一个位置。就像处理“可排序”列表一样。

这种操作不会影响源代码的结构。也就是说,HTML 源码中弹性项目的顺序不会被改变。

order 属性的默认值是 0,它可以取负数或正数。

值得注意的是,弹性项目会根据 order 属性的数值大小进行重新排序——从最小值到最大值。

举个例子就明白了。考虑下面这个无序列表:

1<ul> 2 <li>1</li> 3 <li>2</li> 4 <li>3</li> 5 <li>4</li> 6</ul>

默认情况下,所有弹性项目的 order 值都是 0。经过基本样式设置后,显示效果如下:

No configuration found for ID: 9345d787fb48d4411b66109fb20844f682323e2228107f54ae36e6230caffe87

弹性项目按照 HTML 源码的顺序显示:项目 1、2、3、4。

但如果出于某种原因,你想让项目 1 出现在最后,而又不修改 HTML 文档中的源码顺序呢?

“不修改源码顺序”意味着你不能这样做:

1<ul> 2 <li>2</li> 3 <li>3</li> 4 <li>4</li> 5 <li>1</li> 6</ul>

这时,order 属性就派上用场了。

你只需要将项目 1 的 order 值设为高于其他列表项即可。

如果你曾使用过块级元素的 z-index 属性,就会对这种机制很熟悉。

1/*选择 ul 中的第一个 li 元素 */ 2li:nth-child(1) { 3 order: 1; /*设置一个大于 0 的值。记住,其他弹性项目的 order 默认是 0*/ 4}

弹性项目会按 order 数值从小到大重新排序。

别忘了,默认情况下,项目 2、3 和 4 的 order 值都是 0。

现在,项目 1 的 order 值是 1。

No configuration found for ID: 4397f342c2f40b488f552b968e0da32acf1ffc39f46a869cc2b7fe644811f765

项目 2、3 和 4 的 order 值都是 0,因此 HTML 源码顺序保持不变——没有对默认显示做任何修改。

如果再给项目 2 设置 order: 2 呢?

没错,你猜对了。它也会排到最后,成为 order 值最高的弹性项目。

No configuration found for ID: 33a941cc9db403c6ac30b5b8e0a71766957506c1b49a4384191310a36f1d39c0

</webpackbin

当两个或多个弹性项目具有相同的 order 值时会发生什么?

在下面的例子中,项目 1 和项目 3 被赋予了相同的 order 值:

1li:nth-child(1) { 2 order: 1; 3} 4 5li:nth-child(3) { 6 order: 1; 7}

No configuration found for ID: af8dc1fbf1c3505a6bf4493b862bd20baa1e2b6453ef3c5e1b559f7d18982c5c

</webpackbin

尽管它们的 order 值相同,但仍然按顺序排列:从最低到最高。

这次,项目 3 排在最后,因为它在源文件(HTML 文档)中出现在项目 1 之后。

当多个弹性项目拥有相同的 order 值时,其重新排序依据是它们在源文件中的位置。

以上解释可能有点多。

接下来我们继续看其他属性。

2. Flex grow 和 flex shrink

弹性项目真正的魅力在于它的“灵活性”。

flex-grow 和 flex-shrink 属性让我们能更深入地操控这种“灵活性”。

这两个属性控制弹性项目在有额外空间时是否“扩展”,或在空间不足时是否“收缩”。

它们可以接受从 0 到任意正数的值:0 || 正数

让我来澄清一下。

考虑下面这个简单的无序列表,里面只有一个列表项:

1<ul> 2 <li>I am a simple list</li> 3</ul>
1ul { 2 display: flex; 3}

稍加样式后,显示效果如下:

No configuration found for ID: 4f6e00c3e30b87c5ad22b900b4bc61cbb46f07cf21f84aab974bc9f00777b911

</webpackbin

默认情况下,flex-grow 的值是 0,这意味着弹性项目不会自动扩展以填满可用空间。

值 0 相当于一个“关闭开关”。flex-grow 开关处于关闭状态。

然而,如果你将 flex-grow 的值改为 1,会发生什么?

No configuration found for ID: 348bb68f153210feae9bc1227959381ff2d5e7eddebb2e7739158ce84dece5fc

</webpackbin

此时,弹性项目开始“扩展”,占据全部可用空间。开关已打开!

如果你尝试调整浏览器窗口大小,该项目也会随之“收缩”以适应新的宽度。

为什么?因为默认情况下,flex-shrink 的值是 1,意味着 flex-shrink 开关也是开启的!

稍后我会更详细地讲解 flex-grow 与 flex-shrink,如果你还觉得理解不够清晰的话。

现在我们继续往下看。

3. Flex basis(基础尺寸)

还记得我说过弹性项目的魅力在于“灵活”吗?其实你也可以掌控这种灵活性。

flex-basis 属性用于指定弹性项目的初始大小。这是在 flex-grow 或 flex-shrink 调整其大小之前的基础尺寸。

这句话非常重要,我特意强调一下。

默认值是 flex-basis: auto。flex-basis 可以接受与普通 width 属性相同的任何单位值,例如:百分比 || em || rem || 像素 等。

注意:当设置为零值时,必须带上单位。应写成 flex-basis: 0px,而不是仅写 flex-basis: 0。

我再次回到“单个列表项”的例子。

再次展示这个例子:

1<ul> 2 <li>I am a simple list</li> 3</ul>
1ul { 2 display: flex 3} 4 5li { 6 padding: 4px; /*留出一点间距*/ 7}

默认情况下,弹性项目的初始宽度由 flex-basis: auto 决定。

其宽度会“自动”根据内容大小计算(当然还包括你设置的 padding)。

No configuration found for ID: c2b0747db2fd3d0304a040547c93ec09cad721c59b47b4b600f26004713d12af

</webpackbin

这意味着,如果你增加了弹性项目中的内容,它会自动调整大小以适配。

1<ul> 2 <li>I am a simple list AND I am a simple list</li> 3</ul>

No configuration found for ID: 07ec94c72df4579313def059fe8ff9c46ad27591d753407775e527442d069f17

</webpackbin

但如果你希望将弹性项目固定为某一宽度,也可以这样设置:

1li { 2 flex-basis: 150px; 3}

现在,弹性项目被限制为 150px 的宽度。

No configuration found for ID: 1fd41ffa7932888c65f2d96c6a704a8aa35dab3add506ac44224f7b935bf7b90

</webpackbin

这变得越来越有趣了。

4. Flex 简写属性

flex 简写属性可以一次性设置 flex-grow、flex-shrink 和 flex-basis 三个属性。

建议在合适的情况下,使用 flex 简写属性一次性设置这三个值,而不是分别设置。

1li { 2 flex: 0 1 auto; 3}

这等同于分别设置:

1flex-grow: 0; 2flex-shrink: 1; 3flex-basis: auto;

请注意顺序:
首先是 flex-grow,然后是 flex-shrink,最后是 flex-basis。可以用缩写 GSB 来帮助记忆。

如果在 flex 简写中遗漏了某个值会怎样?

如果只设置了 flex-grow 和 flex-shrink,那么 flex-basis 会默认为 0。

这被称为“绝对弹性项目”。
而如果只设置了 flex-basis,则称为“相对弹性项目”。



1// 这是一个绝对弹性项目 2li { 3 flex: 1 1; // flex-basis 默认为 0 4} 5 6// 这是一个相对弹性项目 7li { 8 flex-basis: 200px; // 仅设置了 flex-basis 9}

我知道你在想:那“相对”和“绝对”弹性项目有什么用呢?

这个问题我会在文章后面解答。目前只需相信这一点即可。

下面我们来看一些非常实用的 flex 简写值。

flex: 0 1 auto

1// 这里的 'li' 代表任意弹性项目 2li { 3 flex: 0 1 auto; 4}

这等同于默认值 flex: 0 1 auto,也就是所有弹性项目的默认行为。

让我稍微拆解一下:


...

flex-basis 设置为 auto,表示弹性项目的初始宽度将自动根据内容大小确定。

明白了吗?

接下来是 flex-grow 值为 0,这意味着 flex-grow 不会改变弹性项目的初始宽度。

生长开关处于关闭状态。

由于 flex-grow 控制项目的“扩展”,而它被设为 0,因此弹性项目不会“扩展”以填满屏幕。

最后,flex-shrink 值为 1,表示“必要时收缩该弹性项目”。

将其应用到几个弹性项目上,效果如下:

No configuration found for ID: b362f8abe0309685f428255fffe3c2eb3b21c772bd8668b29ce01e3b2cb25ae7

</webpackbin

可以看到,弹性项目不会扩展。宽度自动计算,并且在调整浏览器窗口时会按需收缩。

flex: 0 0 auto

1/*这里的 'li' 代表任意列表项 */ 2li { 3 flex: 0 0 auto; 4}

这等同于 flex: none。

按照之前的框架分析:宽度自动计算,但弹性项目既不会增长也不会收缩(两者都设为 0)。

生长和收缩开关均关闭。

本质上,这是一个固定宽度的元素,其初始宽度基于弹性项目中的内容大小。

看看这个简写如何影响两个弹性项目,其中一个包含更多内容:

No configuration found for ID: 98b024e08ae9a92311b6f2398acd886d25bf080a6e2788c6928ab06c62f54d9a

</webpackbin

你首先注意到的是,两个弹性项目的宽度不同。

这是正常的,因为宽度是根据内容大小自动计算的。

尝试调整浏览器窗口大小,你会发现弹性项目不会随宽度缩小。它们会超出父容器,你需要水平滚动才能看到全部内容。


...

flex: 1 1 auto

这等同于 flex: auto。

按照之前的框架分析:
“自动计算初始宽度,但可扩展以填满可用空间,必要时也可收缩。”

生长和收缩开关均开启,宽度自动计算。

No configuration found for ID: 7d464c008ef9c7f402b6758fddc0be62d9bd553aaec41aa4a951177a0ae9d27e

</webpackbin

这次,项目填充了可用空间,并且在调整窗口大小时会自动收缩。

flex: "正数"

其中“正数”代表任意正数(不含引号)

这等同于 flex: "正数" 1 0

例如 flex: 2 1 0 就等于 flex: 2,其中 2 可以是任意正数。

1/*这里的 'li' 代表任意列表项 */ 2li { 3 flex: 2 1 0; /*等同于 flex: 2*/ 4}

按照之前的框架分析:
“将弹性项目的初始宽度设为 0(即无宽度),然后扩展以填满可用空间,最后在可能时收缩。”

既然初始宽度为 0,那宽度是如何计算的?

这时 flex-grow 值接管,决定弹性项目“扩展”的程度。

这就解决了“无宽度”的问题。

这种简写在多个弹性项目初始宽度(flex-basis)为 0px 等零值时特别实用。

真正发生的是:各弹性项目的宽度根据 flex-grow 值的比例来分配。

让我稍作分解。

考虑以下两个列表项:

1<ul> 2 <li>I am One</li> 3 <li>I am Two</li> 4</ul>
1ul { 2 display: flex; 3} 4li:nth-child(1) { 5 flex: 2 1 0; /*等同于 flex: 2*/ 6} 7 8li:nth-child(2){ 9 flex: 1 1 0; 10 background-color: #8cacea; 11}

记住,flex-grow: 1 表示项目会扩展以填满可用空间,生长开关开启。

现在有两个弹性项目,一个 flex-grow 为 1,另一个为 2,结果会怎样?

两个项目的生长开关都开启,但扩展幅度不同:1 和 2。

它们都会扩展以填满可用空间,但按一定比例。

具体怎么分配?

后者占据可用空间的 2/3,前者占据 1/3。

你是怎么得出这个结论的?

这是基本的数学比例:个体比例 / 总比例。希望你没跳过数学课。

No configuration found for ID: e74a2d526a92591b21192b473339894b3678c92a7dea324af0ebb352378fb2e6

</webpackbin

你看到了吗?

尽管两个弹性项目的内容大小相近,但它们占据的空间却不同。

宽度不是基于内容大小,而是基于 flex-grow 的值。

一个大约是另一个的两倍。

5. Align-self(单独对齐)

align-self 属性进一步增强了我们对弹性项目的控制力。

你已经知道 align-items 如何统一控制容器内所有弹性项目的对齐方式。

但如果只想改变单个弹性项目在交叉轴上的位置,而不影响相邻项目呢?

这时 align-self 就派上用场了。

它可以取以下值之一:auto || flex-start || flex-end || center || baseline || stretch

1li:first-of-type { 2 align-self: auto || flex-start || flex-end || center || baseline || stretch 3}

这些值你都不陌生,但为了复习,我再说明一下它们对目标项目的实际影响。

本例中,目标项目是容器中的第一个项目。

该目标弹性项目用红色标出。



flex-end

flex-end 将目标项目对齐到交叉轴的末端。

No configuration found for ID: 08020ba49188e8a50f00408b5f6741c5cc0f1bffcc78c80fa78e6d9cc9335271

</webpackbin

center

center 将目标项目对齐到交叉轴的中心。

No configuration found for ID: 9e9caa82315a6ef802c06b15c1fe3fb1c59f2035877c9444ef4010ff48478125

</webpackbin

stretch

stretch 会“拉伸”目标弹性项目,使其填满交叉轴的可用空间。

No configuration found for ID: ffca520bd51132dd00cf9dfdd44698bd97dfada4ea6fb647a033474b04c6d68d

</webpackbin

baseline

baseline 将目标项目沿基线对齐。

虽然看起来和 flex-start 效果相似,但你应该清楚基线的含义。

我之前已经解释过。

No configuration found for ID: 4330baec70ee8235abe9f554111ba6338768564da74fd5126f71d805a31055cb

</webpackbin

auto

auto 会将目标项目的值设为父级的 align-items 值;若无父级,则默认为 stretch。

在下面的例子中,弹性容器的 align-items 值为 flex-start。

这会使所有弹性项目对齐到交叉轴的起始端。

目标弹性项目继承了父级的 align-items 值,即 flex-start。

No configuration found for ID: 442c77f69950c0d2c3906daf88ff1a2ec26ace5dca151f14d56cc377539032ac

</webpackbin

以上所用弹性项目的基准样式如下,以便你更好地理解:

1ul { 2 display: flex; 3 border: 1px solid red; 4 padding: 0; 5 list-style: none; 6 justify-content: space-between; 7 align-items: flex-start; /*影响所有弹性项目*/ 8 min-height: 50%; 9 background-color: #e8e8e9; 10} 11 12li { 13 width: 100px; 14 background-color: #8cacea; 15 margin: 8px; 16 font-size: 2rem; 17}

弹性容器

绝对尺寸与相对尺寸的弹性项目