弹性项目属性
了解弹性项目的排序、伸缩、基础尺寸和单独对齐属性
我们已经了解了弹性容器及其对齐属性。
确实非常美观。
你已经开始感受到接下来要学习的内容了。
现在,我建议暂时放下弹性容器,转而带你深入了解弹性项目及其对齐属性。
与弹性容器类似,一些对齐属性也适用于所有弹性项目。
让我为你逐一讲解。
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}