Flex布局中的 flex: 0 | 1| none | auto 分别都是什么意思呢?

1,748 阅读6分钟

flex 属性

平时在开发中使用 Flex 布局的频率非常高,但是对于flex的几个值的属性始终是含糊不清,此次就来把这些模糊的点搞明白。

flex是一个简写属性,用于同时设置flex-grow(放大比例)、flex-shrink(缩小比例)和flex-basis(基础大小)这三个子属性。默认值为0 1 auto,后面两个属性可选。

flex-grow

flex-grow 属性定义项目的放大比例,可以设置任意非负数字(正小数、正整数、0),默认是0,如果存在剩余空间,也不会放大。 image.png 接下来我们将 2flex-grow 设置为 1 ,可以看到编号为2的元素撑满了剩余空间。 image.png 如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。 image.png 如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍,2元素的值为 1 ,3元素则为 2 。 image.png

这里的计算是有一个公式的,首先我们要知道剩余空间是多少,主容器为 500 像素,每个子元素为 100 像素,所以知道我们的剩余空间还有 200 像素 。

1 元素所得的空间: 200(主容器剩余空间) * 1(1元素设置的 flex-grow值) / 2(flex-grow总和) = 100像素

1 元素最终的实际宽度为: 100 + 100 = 200 像素

2 元素所得的空间: 200(主容器剩余空间) * 1(2元素设置的 flex-grow值) / 2(flex-grow总和) = 100像素

2 元素最终的实际宽度为: 100 + 100 = 200 像素

image.png

总结一下公式,flex项最终宽度 = flex项基础宽度 + (容器剩余空间 * flex项设置的 flex-grow值 / 所有flex项的 flex-grow和)

flex-shrink

flex-shrink属性定义了项目的缩小比例,非负数字(正小数、正整数、0),默认值是1,当空间不足时,该项目将缩小,设置了 flex-shrink 为1无变化。 image.png

如果所有项目的 flex-shrink 属性都为1,当空间不足时,都将等比例缩小。我们试着改变子元素的宽度,由100变为300,会发现并没有超出容器,而是等分了空间比例。 image.png 如果把子元素的 flex-shrink 设置为 0 就不会缩小了。 image.png

再来看一下 flex-shrink 的计算规则。

我们父级的容器还是500像素,这次我们将每个子元素设置为150像素,再加一个编号4的子元素,并将2元素的 flex-shrink 设置为1,4 元素的flex-shrink 为2。此时溢出父容器 100 像素。

接下来我们还需知道总权重, 每个元素的权重计算规则: 每个flex项收缩权重 = flex-shrink * flex项宽度

2 元素的权重为: 1 * 150 = 150像素

4 元素的权重为: 2 * 150 = 300像素

总权重 = 450像素

2 元素的收缩值为: 100(溢出空间) * ( 150(每个flex项目权重) / 450(总权重)) = 33.33

2 元素的实际宽度为: 150 - 33.33 = 116.66

4 元素的收缩值为: 100(溢出空间) * ( 300(每个flex项目权重) / 450(总权重)) = 66.66

4 元素的实际宽度为: 150 - 66.66 = 83.33

image.png

总结一下公式,flex项最终宽度 = flex项基础宽度 - (溢出空间 * 每个flex项目权重 / 总权重)

flex-basis

flex-basis 指定了 flex 元素在主轴方向上的初始大小。他的默认值是auto, 即项目的本来大小。

flex-basis:auto 如果该元素未指定宽度,则宽度将根据内容决定。

定义 flex 元素的 flex-basis 属性。若值为0,则必须加上单位,以免被视作伸缩性。省略时默认值为 0。(初始值为 auto)

flex: 0 | 1| none | auto

回到我们文章要探讨的问题。flex: 0 | 1| none | auto 分别都是什么意思呢?

flex: 0 1 auto

flex 的默认属性就是 flex: 0 1 auto。 由上面可知,默认属性代表不放大,可以缩小,宽度大小为自动。如下图没有设置任何属性,子容器的宽度已经超出了父容器(父容器500像素,子容器每个200像素)。可以看到最终每个flex项,都有缩小。

image.png

flex: auto

首先来看下设置了flex: auto 是否可以放大,如下父元素还是 500 像素,每个子元素为 100 像素。 可以看出子元素是能放大的。

image.png

是否可以缩小呢?来试一下将子元素设置为 300,父元素不变。看到可以缩小。

image.png

可以得出结论,flex: auto 相当于 flex: 1 1 auto, 即可以放大,可以缩小,宽度将根据内容决定。

flex: 0

下图是设置了 flex: 0,的属性,可以看到元素已经缩小到只有内容了,看一下 MDN ,对于flex的单值解释。

  • 一个 <flex-grow> 的有效值:此时简写会扩展为 flex: <flex-grow> 1 0

那么flex: 0 也就相当于flex: 0 1 0。不放大,可以缩小。

image.png

flex: 1

了解了 flex: 0, 那么就很容易知道flex:1 相当于 flex: 1 1 0, 也就是可以放大,可以缩小

image.png

flex: none

flex: none, 相当于 flex: 0 1 auto, 从属性可以看出是不放大可以缩小。

image.png

疑惑

flex: none 和 flex: 0

flex: 0flex: none 都是不可以放大,但是可以缩小,那么他们的区别是什么呢?

它们的区别在于flex-basis,看一下MDN的描述

当一个元素同时被设置了 flex-basis (除值为 auto 外) 和 width (或者在 flex-direction: column 情况下设置了height) , flex-basis 具有更高的优先级。

也就是说在有设置宽度的情况下,flex: none ,用的是元素本身的宽度。而flex: 0 则由内容撑开。

flex: auto 和 flex: 1

flex: autoflex: 1 1 auto 的简写,flex: 1flex: 1 1 0 的简写,它们之间的区别还是在于 flex-basis

如果容器有足够的空间,flex:1flex:auto 都会平分剩余空间,但是 flex:auto 会保持项目本身的最小宽度。

如果容器没有足够的空间,flex:1 会优先压缩内容,使得所有项目都能等分空间,而 flex:auto 会优先保持内容的完整性,挤压其他项目的空间。

flex: auto;

image.png

flex: 1

image.png