引子
有关于 flex-shrink
,flex-grow
属性,是如何计算的,前人已经有了很多总结,本篇是在本人学习flex
过程中遇到问题后,再进行思考,对flex-shrink
属性的进一步拓展。
总结前人的flex-shrink计算公式
首先看一下主要的HTML
结构:
<section class='container'>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
</section>
再看一下主要的LESS
设置:
.container{
dispaly: flex;
flex-basis: 600px;
height: 100px;
.item{
&:nth-child(1){
flex-shrink: 1;
flex-basis: 200px;
}
&:nth-child(2){
flex-shrink: 3;
flex-basis: 600px;
}
&:nth-child(3){
flex-shrink: 1;
flex-basis: 400px;
}
}
}
最终效果图如下:

根据已有的结论,与效果图,我们给出前人的计算公式思想:
:容器中第
个项目经过
flex
伸缩变化之后最终的宽度: 容器中第
个项目所占有的伸缩系数
flex-shrink
:容器的宽度
: 容器中第
个项目的宽度,即项目的属性
width | flex-basis
的值: 容器中第
个项目所占有的权重,即
: 求和函数,求
到
的表达式的和
有以上定义之后,即可得出以下定义:
: 溢出宽度,即:
:项目总权重,即:
最终得到的公式为:
将变量带入计算公式可算出3个盒子的宽度:
padding
与margin
让我们稍微改动一下LESS
,查看存在 padding 时的盒子的宽度:
.container.padding{
.item{
padding: 100px;
&:nth-child(1){
flex-shrink: 1;
flex-basis: 200px;
}
&:nth-child(2){
flex-shrink: 5;
flex-basis: 800px;
}
&:nth-child(3){
flex-shrink: 1;
flex-basis: 400px
}
}
}
最终的效果图如下:

仔细观察可以发现,加了 padding 之后, padding 值并未受到影响,减小的仅仅是盒子的真实宽度,如图第二个div的宽度完全由 padding 组成:

由此特性,我们更新一下定义:
: 容器中第
个项目的各个外边距宽度和, 由
padding,border,margin
属性值的加和: 容器中第
个项目的盒子宽度(
),由
(width | flex-basis)
属性值加上所有边距组成: 溢出宽度,即:
于是有新公式:
我们将所有变量带入计算可有:
诶,等一下,好像有哪里不对???和显示的数值不太一样。第一个盒子,明明是175px
,第二个盒子,明明是100px
,现在需要讲讲下一个特性
min-width 对 flex-shrink 的影响
在写文档之前曾有过这样的一段LESS
设置:
.container.min-width{
.item{
flex-basis: 600px;
&:nth-child(1){
flex-shrink: 1;
}
&:nth-child(2){
flex-shrink: 3;
min-width: 150px;
}
&:nth-child(3){
flex-shrink: 2;
}
}
}
得到的效果图如下:

此时第一个盒子可以推算出被减去的250是这么来的:
大胆推测:在min-width
被触发的时候,被触发的项目的flex-shrink
的值应该为0
,计算项目的总宽度时,触发min-width
的项目宽度值,取为min-width
属性值
我们可以尝试上面得到的结论去计算刚刚的padding
,由于padding
不会受到影响,所以盒子的最小宽度只能是100px
,而那时候min-width
被触发了,此时min-width
为0
:
计算公式终于正确了!
其实我们对之前错误的计算方式这样看(即,flex-shrink
形变后的项目的宽度由各个边距的宽度加上项目形变后的真实宽度):
这样我们在计算第二个项目时就能发现问题所在(注意,当时计算的溢出宽度是800px):
项目的真实宽度width
属性值在经过形变之后居然变成了负值,这显然是不正确的。所以可推导出flex-shrink
的变化,最多只能够使得项目的width
的值与min-width
一致。
结论
综上所述,我们最后可以来一个终极公式了:
:容器中第
个项目经过
flex
伸缩变化之后最终的宽度: 容器中第
个项目所占有的伸缩系数
flex-shrink
:容器的宽度
: 容器中第
个项目的宽度,即项目的属性
width | flex-basis
的值: 容器中第
个项目所占有的权重,即
: 容器中第
个项目的各个外边距宽度和, 由
padding,border,margin
属性值的加和: 容器中第
个项目的盒子宽度(
),由
(width | flex-basis)
属性值加上所有边距组成: 求和函数,求
到
的表达式的和
: 溢出宽度,即:
:项目总权重,即:
: 描述
min-width
被触发的特殊情况,当flex-shrink
形变后的某一项计算得到的width === min-width
时,该项的flex-shrink
变成0
,也变成
min-width
,每一个项目将重新计算
有公式:
结语
啰里啰唆讲了这么多,希望有看客能理解其flex-shrink
的计算方式了。如有不合理之处还望指正。flex-grow
的计算与flex-shrink
不一致,但相对简单,不再叙述,其特殊的地方应该在max-width
值的设置处。