flex-grow
第一步:计算剩余空间
- flex-grow的和大于1时:剩余空间 = 父容器宽度 - 子元素总宽度
- flex-grow的和小于1时:剩余空间 = ( 父容器宽度 - 子元素总宽度 ) * ( flex-grow的和 / 1)
第二步:计算各子元素分配到的空间
- 总权重:flex-grow的和
- 各个权重:格子flex-grow的值
- 分配的空间:剩余空间 * ( 各个权重 / 总权重)
第三步:计算扩张后的总空间
举例说明
基本结构
<div class="parent">
<div class="child one"></div>
<div class="child two"></div>
<div class="child three"></div>
</div>
flex-group和大于1的情况
.parent{
display: flex;
width: 500px;
height: 100px;
background-color: #000;
}
.child{
height: 80px;
}
.one{
flex-grow: 2;
width: 120px;
background-color: red;
}
.two{
flex-grow: 1;
width: 150px;
background-color: green;
}
.three{
flex-grow: 0;
width: 200px;
background-color: blue;
}
计算过程
- 剩余空间:500 - (120 + 150 + 200) = 30
- 分配到的空间:
- one: 30 * (2 / 3) = 20
- two: 30 * (1 / 3) = 10
- three: 30 * (0 / 3) = 0
- 最终大小:
- one: 120 + 20 = 140
- two: 150 + 10 = 160
- three: 200 + 0 = 200

flex-group和小于1的情况
.one{
flex-grow: 0.2;
width: 120px;
background-color: red;
}
.two{
flex-grow: 0.1;
width: 150px;
background-color: green;
}
.three{
flex-grow: 0.3;
width: 200px;
background-color: blue;
}
计算过程
- 剩余空间:(500 - (120 + 150 + 200)) * ((0.2 + 0.1 + 0.3) / 1) = 30 * 0.6 = 18
- 分配到的空间:
- one: 18 * (0.2 / 0.6) = 6
- two: 18 * (0.1 / 0.6) = 3
- three: 18 * (0.3 / 0.6) = 9
- 最终大小:
- one: 120 + 6 = 126
- two: 150 + 3 = 153
- three: 200 + 9 = 209

flex-shrink
第一步:计算溢出值(负数)
- flex-shrink的和大于1时:溢出值 = 父容器宽度 - 子元素总宽度
- flex-shrink的和小于1时:溢出值 = (父容器宽度 - 子元素总宽度) * (flex-shrink的和 / 1)
第二步:按权重分配溢出值
- 总权重:(项目宽度 * flex-shrink) 求和
- 各个权重:项目宽度 * flex-shrink
- 项目溢出值:总溢出值 * (各个权重 / 总权重)
第三步:计算收缩后的总空间
举例说明
flex-shrink和大于1的情况
.parent{
display: flex;
width: 400px;
height: 100px;
background-color: #000;
}
.child{
height: 80px;
}
.one{
flex-shrink: 2;
width: 120px;
background-color: red;
}
.two{
flex-shrink: 1;
width: 150px;
background-color: green;
}
.three{
flex-shrink: 3;
width: 200px;
background-color: blue;
}
计算过程
- 溢出值:400 - (120 + 150 + 200) = -70
- 各个溢出值:
- 总权重:120 * 2 + 150 * 1 + 200 * 3 = 990
- one: -70 * (120 * 2 / 990) = -16.97
- two: -70 * (150 * 1 / 990) = -10.61
- three: -70 * (200 * 3 / 990) = -42.42
- 最终大小:
- one: 120 + (-16.97) = 103.03
- two: 150 + (-10.61) = 139.39
- three: 200 + (-42.42) = 157.58

flex-shrink和小于1的情况
.one{
flex-shrink: 0.2;
width: 120px;
background-color: red;
}
.two{
flex-shrink: 0.1;
width: 150px;
background-color: green;
}
.three{
flex-shrink: 0.3;
width: 200px;
background-color: blue;
}
计算过程
- 溢出值:(400 - (120 + 150 + 200)) * ((0.2 + 0.1 + 0.3) / 1)= -70 * 0.6 = -42
- 各个溢出值:
- 总权重:120 * 0.2 + 150 * 0.1 + 200 * 0.3 = 99
- one: -42 * (120 * 0.2 / 99) = -10.18
- two: -42 * (150 * 0.1 / 99) = -6.36
- three: -42 * (200 * 0.3 / 99) = -25.45
- 最终大小:
- one: 120 + (-10.18) = 109.82(这里和Chrome浏览器实际结果差0.01,等查明计算规则后写明)
- two: 150 + (-6.36) = 143.64
- three: 200 + (-25.45) = 174.55

总结
差异宽度的计算(第一步中的值的计算)
- 如果所有元素的 flex-grow/shrink 之和大于等于 1,则所有子元素的尺寸一定会被调整到适应父元素的尺寸(在不考虑 max/min-width/height 的前提下)即 父容器宽度 - 子元素总宽度
- 而如果 flex-grow/shrink 之和小于 1,则只会 grow 或 shrink 所有元素 flex-grow/shrink 之和相对于 1 的比例。即 (父容器宽度 - 子元素总宽度) * (flex-grow/shrink 之和 / 1)
权重的计算(第二步中值的计算)
- grow 时的每个元素的权重即为元素的 flex-grow 的值;即 各个扩张因子/扩张因子的和
- shrink 时每个元素的权重则为元素 flex-shrink 乘以 width 后的值;即 (收缩因子 * 项目宽度)/ ((收缩因子 * 项目宽度)的和)
补充:flex-shrink和<1时计算结果和实际渲染结果
计算结果 | 109.82 | 143.64 | 174.55 |
Chrome Mac屏幕 | 109.82 | 143.63 | 174.55 |
Chrome 其他屏幕 | 109.81 | 143.64 | 174.55 |
Safari | 110 | 144 | 175 |