關於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值的設置處。

參考

相關文章
相關標籤/搜索