关于 flex-grow 和 flex-shrink 的计算
Flex-Grow
容器1 固定宽度为 500px . 子元素 A, B, C 和 F 的 flex-grow 属性为 1 . 子元素 D 和 E 的 flex-grow 的属性为 2 .
<div id="container1">
<div class="box1" style="background-color:red;">A</div>
<div class="box1" style="background-color:lightblue;">B</div>
<div class="box1" style="background-color:yellow;">C</div>
<div class="box2" style="background-color:brown;">D</div>
<div class="box2" style="background-color:lightgreen;">E</div>
<div class="box1" style="background-color:brown;">F</div>
</div>
#container1 {
display: flex;
justify-content: space-around;
flex-flow: row wrap;
align-items: stretch;
font-family: monospace;
font-size: 20px;
line-height: 28px;
width: 500px;
height: 28px;
}
.box1 {
flex-grow: 1;
}
.box2 {
flex-grow: 2;
}
最终显示效果如下:
子元素根据 flex-grow 扩增的规则是,容器的宽度减去子元素的宽度,得到剩余宽度,再按照 flex-grow 的比例进行分配。即使子元素没有指定宽度,子元素中的内容(此例中为英文字符)其实还是需要计算宽度的。计算过程如下:
容器宽度为 500px,每个子元素中的内容宽度为 12px。
剩余宽度为:500px - 6*12px = 428px。
flex-grow 为 1 的子元素在原来 12px 的基础上增加 428px/8 = 53.5px,最终宽度为 65.5px。
flex-grow 为 2 的子元素在原来 12px 的基础上增加 2*428px/8 = 107px,最终宽度为 119px。
容器2 固定宽度为 500px . 子元素 A, B, C 和 F 宽度为 50px 并且 flex-grow 属性为 1 . 子元素 D 和 E 未指定宽度,flex-grow 属性为 2。
<div id="container2">
<div class="box3" style="background-color:red;">A</div>
<div class="box3" style="background-color:lightblue;">B</div>
<div class="box3" style="background-color:yellow;">C</div>
<div class="box4" style="background-color:brown;">D</div>
<div class="box4" style="background-color:lightgreen;">E</div>
<div class="box3" style="background-color:brown;">F</div>
</div>
#container2 {
display: flex;
justify-content: space-around;
flex-flow: row wrap;
align-items: center;
font-family: monospace;
font-size: 20px;
line-height: 28px;
width: 500px;
height: 28px;
}
.box3 {
width: 50px;
height: 28px;
flex-grow: 1;
}
.box4 {
height: 28px;
flex-grow: 2;
}
最终显示效果如下:
计算过程如下:
容器宽度为 500px,其中4个子元素的宽度设定为 50px,剩余 2 个子元素宽度未设定,但是内容宽度为 12px。
剩余宽度为:500px - 4*50px - 2*12px = 276px。
flex-grow 为 1 的子元素在原来 50px 的基础上增加 276px/8 = 34.5px,最终宽度为 84.5px。
flex-grow 为 2 的子元素在原来 12px 的基础上增加 2*276px/8 = 69px,最终宽度为 81px。
小结
子元素最终的显示宽度与 flex-grow 并不成正比。flex-grow 属性值为 2 的子元素宽度不一定是 flex-grow 为 1 的子元素宽度的 2 倍。最终的显示宽度不仅和 flex-grow 属性有关,还和子元素中的内容宽度有关。注意:我特意指定了子元素中的字体为 monospace 等宽字体,每个子元素中只显示一个字母,这样方便计算元素的内容宽度,也有利于排除元素中内容的影响。
Flex-Shrink
容器3 的固定宽度为 500px . 子元素 A, B, C 和 F 的宽为 100px, flex-shrink 属性为 1。子元素 D 和 E 的宽为 200px,flex-shrink 属性为 2。
<div id="container3">
<div class="box5" style="background-color:red;">A</div>
<div class="box5" style="background-color:lightblue;">B</div>
<div class="box5" style="background-color:yellow;">C</div>
<div class="box6" style="background-color:brown;">D</div>
<div class="box6" style="background-color:lightgreen;">E</div>
<div class="box5" style="background-color:brown;">F</div>
</div>
#container3 {
display: flex;
justify-content: space-around;
align-items: center;
font-family: monospace;
font-size: 20px;
line-height: 28px;
width: 500px;
height: 28px;
}
.box5 {
width: 100px;
height: 28px;
flex-shrink: 1;
}
.box6 {
width: 200px;
height: 28px;
flex-shrink: 2;
}
最终显示效果如下:
如果子元素的宽度加起来超过容器的宽度,那么就需要各子元素按照一定规则进行缩减。计算方法是,先用子元素的宽度总和减去容器宽度,得到溢出宽度,溢出宽度需要各子元素缩减一定比例,而这些比例与子元素的 flex-shrink 属性正相关。计算过程如下:
容器宽度为 500px,4 个子元素的宽度为 100px,2个子元素的宽度为 200ppx。
溢出宽度为:4*100px + 2*200px - 500px = 300px。
设 flex-shrink = 1 的子元素缩减 n (n < 1),那么flex -shrink = 2 的子元素缩减 2n。
flex-shrink = 1 的子元素总共缩减 4*100*npx,flex-shrink = 2 的子元素总共缩减 2*200*2npx。所有子元素缩减的像素要等于溢出宽度。即:
4*100*npx + 2*200*2npx = 300px
解得:n = 0.25
所以,A,B,C,F 4个子元素最终的宽度为 100px * (1 - 0.25) = 75px。D,E 2个子元素最终的宽度为 200px * (1 - 2 * 0.25) = 100px。
容器4的固定宽度为 500px . 子元素 A, B, C 和 F 的宽为 100px,flex-shrink 属性为 1。子元素 D 和 E 宽为 200px,最小宽度为 80px,flex-shrink 属性为 2。
<div id="container4">
<div class="box7" style="background-color:red;">A</div>
<div class="box7" style="background-color:lightblue;">B</div>
<div class="box7" style="background-color:yellow;">C</div>
<div class="box8" style="background-color:brown;">D</div>
<div class="box8" style="background-color:lightgreen;">E</div>
<div class="box7" style="background-color:brown;">F</div>
</div>
#container4 {
display: flex;
justify-content: space-around;
align-items: center;
font-family: monospace;
font-size: 20px;
line-height: 28px;
width: 500px;
height: 28px;
}
.box7 {
width: 100px;
height: 28px;
flex-shrink: 1;
}
.box8 {
width: 200px;
min-width: 80px;
height: 28px;
flex-shrink: 2;
}
容器5的固定宽度为 500px。子元素 A, B, C 和 F 宽为 100px,and flex-shrink 属性为 1。子元素 D 和 E 宽为 200px,最小宽度为 150px,flex-shrink 属性为 2。
<div id="container5">
<div class="box9" style="background-color:red;">A</div>
<div class="box9" style="background-color:lightblue;">B</div>
<div class="box9" style="background-color:yellow;">C</div>
<div class="box10" style="background-color:brown;">D</div>
<div class="box10" style="background-color:lightgreen;">E</div>
<div class="box9" style="background-color:brown;">F</div>
</div>
#container5 {
display: flex;
justify-content: space-around;
align-items: center;
font-family: monospace;
font-size: 20px;
line-height: 28px;
width: 500px;
height: 28px;
}
.box9 {
width: 100px;
height: 28px;
flex-shrink: 1;
}
.box10 {
width: 200px;
min-width: 150px;
height: 28px;
flex-shrink: 2;
}
容器6的固定宽度为 500px。子元素 A, B, C 和 F 宽为 100px,flex-shrink 属性为 1。子元素 D 和 E 宽为 200px,flex-shrink 属性为 2。但是子元素 D 最小宽度为 150px。
<div id="container6">
<div class="box11" style="background-color:red;">A</div>
<div class="box11" style="background-color:lightblue;">B</div>
<div class="box11" style="background-color:yellow;">C</div>
<div class="box12" style="background-color:brown;">D</div>
<div class="box13" style="background-color:lightgreen;">E</div>
<div class="box11" style="background-color:brown;">F</div>
</div>
#container6 {
display: flex;
justify-content: space-around;
align-items: center;
font-family: monospace;
font-size: 20px;
line-height: 28px;
width: 500px;
height: 28px;
}
.box11 {
width: 100px;
height: 28px;
flex-shrink: 1;
}
.box12 {
width: 200px;
min-width: 150px;
height: 28px;
flex-shrink: 2;
}
.box13 {
width: 200px;
height: 28px;
flex-shrink: 2;
}
以上三个容器(4,5,6)的最终显示效果为:
由上面三个容器可以看到,子元素宽度会优先按照 flex-shrink 进行分配,如果某些子元素分配的宽度小于它们的最小宽度,那么这些子元素宽度将不按照 flex-shrink 规则进行分配,直接使用最小宽度。剩余元素来分担容器的溢出宽度。
我们来计算一下容器6的子容器宽度。如果按照 flex-shrink 规则进行分配,D的宽度应该是100px,超过了它的最小宽度。D就按最小宽度计算,溢出宽度由其他子元素承担。
如果D按照最小宽度计算,那么溢出宽度就变为 4*100px + 150px + 200px - 500px = 250px
设A,B,C,F缩减 n (n < 1),那么E就要缩减 2n。
A,B,C,F一共缩减 4*100npx,E缩减 200*2npx。它们缩减的总宽度等于溢出宽度。即:
4*100npx + 200*2npx = 250px
解得:n = 0.3125
所以,A,B,C,F 4个子元素的宽度分别为 100px * (1 - 0.3125) = 68.75px。E的宽度为 200px * (1 - 2* 0.3125) = 75px。
参考文章: