0%

flex-grow与flex-shrink的计算

介绍flex-grow与flex-shrink的比例如何计算。

先放几张之前的图

计算

flex-grow

  当剩余空间为 x,三个元素的 flex-grow 分别为 a,b,c。设 sum 为 a + b + c。那么三个元素将得到剩余空间分别是 x * (a / sum), x * (b / sum), x * (c / sum),这是他们各自的权重。

举个栗子:

父元素宽度 500px,三个子元素的 width 分别为 100px150px100px

于是剩余空间为 150px

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

三个元素的 flex-grow 分别是 1,2,3,于是 sum 为 6
则三个元素所得到的多余空间分别是:


150 * (1 / 6) = 25px
150 * (2 / 6) = 50px
150 * (3 / 6) = 75px

三个元素最终的宽度分别为 125px,200px,175px。

100px + 25px = 125px
150px + 50px = 200px
100px + 75px = 175px

  还有一种情况,当所有元素的 flex-grow 之和小于 1 的时候(注意是 1,也就是说每个元素的 flex-grow 都是一个小数。),上面式子中的 sum 将会使用 1 来参与计算,而不论它们的和是多少。
  也就是说,当所有的元素的 flex-grow 之和小于 1 的时候,剩余空间不会全部分配给各个元素。实际上用来分配的空间是 (flex-grow / 1) * 剩余空间,这些用来分配的空间依然是按 flex-grow 的比例来分配。

举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

三个元素的 flex-grow 分别是 0.1,0.2,0.3。
则三个元素所得到的多余空间分别是:

150 * (0.1 / 1) = 15px
150 * (0.2 / 1) = 30px
150 * (0.3 / 1) = 45px

150px - 15px - 30px - 45px = 60px,即还有 60px 没有分配给任何子元素。

三个元素的最终宽度分别为:

100px + 15px = 115px
150px + 30px = 180px
100px + 45px = 145px

  另外,flex-grow 还会受到 max-width 的影响。如果最终 grow 后的结果大于 max-width 指定的值,max-width 的值将会优先使用。同样会导致父元素有部分剩余空间没有分配。

  以上就是 flex-grow 的计算方式。

flex-shrink

  n既然可以在空间有多余时把多余空间分配给各个子元素,当然也可以在空间不够时让各个子元素收缩以适应有限的空间了,这就是 flex-shrink 属性的作用。你可能会觉得 flex-shrink 的计算方式跟 flex-grow 很类似,然而事情并没有这么简单。

  flex-shrink 属性定义空间不够时各个元素如何收缩。其值默认为 1。很多文章对此基本是一笔带过:“flex-shrink 属性定义了元素的收缩系数”,根本就不说它具体是怎么计算的。flex-shrink 定义的仅仅只是元素宽度变小的一个权重分量。

  每个元素具体收缩多少,还有另一个重要因素,即它本身的宽度。

举个栗子:

父元素 500px。三个子元素分别设置为 150px,200px,300px。

三个子元素的 flex-shrink 的值分别为 1,2,3。

首先,计算子元素溢出多少:150 + 200 + 300 - 500 = -150px

那这 -150px 将由三个元素的分别收缩一定的量来弥补。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

具体的计算方式为:每个元素收缩的权重为其 flex-shrink 乘以其宽度。

所以总权重为 1 * 150 + 2 * 200 + 3 * 300 = 1450

三个元素分别收缩:

[150 * (1(flex-shrink) * 150(width))] / 1450 = -15.5
[150 * (2(flex-shrink) * 200(width))] / 1450 = -41.4
[150 * (3(flex-shrink) * 300(width))] / 1450 = -93.1

其中150为溢出空间

三个元素的最终宽度分别为:

150 - 15.5 = 134.5
200 - 41.4 = 158.6
300 - 93.1 = 206.9

  同样,当所有元素的 flex-shrink 之和小于 1 时,计算方式也会有所不同,此时,并不会收缩所有的空间,而只会收缩 flex-shrink 之和相对于 1 的比例的空间。

举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

还是上面的例子,但是 flex-shrink 分别改为 0.1,0.2,0.3。

于是总权重为 145(正好缩小 10 倍,略去计算公式。)。

三个元素收缩总和并不是 150px,而是只会收缩 150px 的 [(0.1 + 0.2 + 0.3) / 1] 即 60% 的空间:90px。

每个元素收缩的空间为:

90 * 0.1(flex-shrink) * 150(width) / 145 = 9.31
90 * 0.2(flex-shrink) * 200(width) / 145 = 24.83
90 * 0.3(flex-shrink) * 300(width) / 145 = 55.86

三个元素的最终宽度分别为:

150 - 9.31 = 140.69
200 - 24.83 = 175.17
300 - 55.86 = 244.14

  当然,类似 flex-grow,flex-shrink 也会受到 min-width 的影响。

  以上就是 flex-grow 的计算方式。

总结

  虽然上面的公式看起来很复杂,其实计算过程还是比较简单的:如果所有元素的 flex-grow/shrink 之和大于等于 1,则所有子元素的尺寸一定会被调整到适应父元素的尺寸(在不考虑 max/min-width/height 的前提下),而如果 flex-grow/shrink 之和小于 1,则只会 grow 或 shrink 所有元素 flex-grow/shrink 之和相对于 1 的比例。grow 时的每个元素的权重即为元素的 flex-grow 的值;shrink 时每个元素的权重则为元素 flex-shrink 乘以 width 后的值。

转改自知乎

bulb