关于flex-shrink计算:再深刻一点点

引子

有关于 flex-shrinkflex-grow 属性,是如何计算的,前人已经有了不少总结,本篇是在本人学习flex过程当中遇到问题后,再进行思考,对这两个属性的进一步拓展。css

前人总结的计算公式

首先看一下主要的HTML结构:html

<section class='container'>
	<div class='item'></div>
    <div class='item'></div>
    <div class='item'></div>
</section>
复制代码

再看一下主要的LESS设置:es6

.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;
        }
    }
}
复制代码

最终效果图以下: less

不带有padding与margin的flex-box

根据已有的结论,与效果图,咱们给出前人的计算公式:函数

  • W_c :容器的宽度post

  • W_ri: 容器中第i个项目的真实宽度学习

  • W_fi :容器中第i个项目通过flex伸缩变化以后最终的宽度flex

  • S_i : 容器中第i个项目所占有的伸缩系数flex-shrinkflexbox

  • \sum_i^n(exp) : 求和函数,求in的表达式的和es5

有以上定义以后,便可得出公式:

W_fi = W_ri - (( \sum_i^n W_ri) - W_c) \times \frac {W_ri \times S_i}{ \sum_i^n W_ri \times S_i }

例如:

W_f1 = 200 - ((200px + 600px + 400px) - 600px) \times \frac {200 \times 1}{200\times1 + 600 \times 3 + 400 \times 1} \\
W_f1 = 200 - 600 \times \frac{200}{4 \times 600} = 200 - \frac{200}{4} = 150px

同上可有:

W_f2 = 600 - 600 \times \frac{600 \times 3}{ 4 \times 600 } = 150px \\
W_f3 = 400 - 600 \times \frac{400 \times 1}{ 4 \times 600 } = 300px

paddingmargin

让咱们稍微改动一下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 的 flex-shrink 盒子

仔细观察能够发现,加了 padding 以后, padding 值并未受到影响,减少的仅仅是盒子的真实宽度,如图第二个div的宽度彻底由 padding 组成:

加了padding后, padding并未受到影响

由此特性便可推导出新的特性:

  • W_bi : 容器中第i个项目的盒子宽度(W_bi = W_ri + padding + border + margin),由真实宽度加上全部边距组成

因而有新公式:

W_fi = W_bi - (( \sum_i^n W_bi) - W_c) \times \frac {W_ri \times S_i}{ \sum_i^n W_ri \times S_i })

咱们带入计算可有:

W_f1 = (100+50\times2) - ((100 + 700 + 300 + 50\times6) - 600)\times\frac{100\times1}{100\times1+700\times5+300\times1}\\
W_f1 = 200 - 800\times\frac{100}{3900} = 179.4871794871794

同理有:

W_f2 = 800 - 800\times\frac{700\times5}{3900} = 82.0512820512821

诶,等一下,好像有哪里不对???和显示的数值不太同样。第一个盒子,明明是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;
        }
    }
}
复制代码

获得的效果图以下:

flex-shrink 盒子设置 min-width

此时第一个盒子能够推算出: 250 = (600\times2+150-600) \times\frac{600\times1}{600\times1 + 600\times2 }

能够推出,min-width被触发的时候,被触发的项目的flex-shrink的值应该为0,计算项目的总宽度时,触发min-width的项目宽度值,取为min-width属性值

咱们能够尝试上面获得的结论去计算刚刚的padding,因为padding不会受到影响,因此盒子的最小宽度只能是100px,而那时候min-width被触发了,此时min-width0

W_f1 = (100+50\times2) - ((100 + 0 + 300 + 50\times6) - 600)\times\frac{100\times1}{100\times1+700\times0+300\times1}\\
W_f1 = 200 - 100\times\frac{100}{400} = 175

计算公式终于正确了!

其实咱们对以前错误的计算方式这样看(即,flex-shrink形变后的项目的宽度由各个边距的宽度加上项目形变后的真实宽度):

W_fi = (W_bi-W_ri) + (W_ri - (( \sum_i^n W_bi) - W_c) \times \frac {W_ri \times S_i}{ \sum_i^n W_ri \times S_i })

这样计算第二个项目时就能发现问题所在:

W_f1 = (700 + 50\times2 - 700) + (700 - ((100 + 700 + 300 + 50\times6) - 600)\times\frac{100\times1}{100\times1+700\times5+300\times1})\\
W_f1 = 100 + (700 - 800\times\frac{35}{39}) = 100 + (-17.9487179487179)

项目的真实宽度width属性值在通过形变以后竟然变成了负值,这显然是不正确的。因此可推导出flex-shrink的变化,最多只可以使得项目的width的值与min-width一致。

结论

综上所述,咱们最后能够来一个终极公式了:

  • W_c:容器的宽度

  • W_ri: 容器中第i个项目的真实宽度,widthflex-basic属性决定

  • W_bi: 容器中第i个项目的盒子宽度(W_bi = W_ri + padding + border + margin),由真实宽度加上全部边距组成

  • W_fi:容器中第i个项目通过flex伸缩变化以后最终的宽度,咱们要求的值

  • S_i : 容器中第i个项目所占有的伸缩系数flex-shrink

  • \sum_i^n(exp) : 求和函数,求in的表达式的和

  • \alpha : 描述min-width被触发的特殊状况,当flex-shrink形变后的某一项计算获得的width === min-width时,该项的flex-shrink变成0W_r也变成min-width,每个项目将从新计算

有公式:

W_fi = (W_bi - W_ri) + \alpha(W_ri - (( \sum_i^n W_bi) - W_c) \times \frac {W_ri \times S_i}{ \sum_i^n W_ri \times S_i })

结语

啰里啰唆讲了这么多,但愿有看客能理解其中的意思。若有不合理之处还望指正。flex-grow的计算与flex-shrink十分类似,其特殊的地方应该在max-width值的设置处。

参考

相关文章
相关标签/搜索