作者:Scott Domes
編譯:胡子大哈
翻譯原文:http://huziketang.com/blog/posts/detail?postId=58acfdc6204d50674934c3aa
英文原文:Even more about how Flexbox works?—?explained in big, colorful, animated gifs
** 轉載請注明出處,保留原文鏈接以及作者信息**

在上一篇文章中,我們介紹了 flexbox 的幾個屬性: flex-direction
,justify-content
,align-items
和 align-self
。
這些屬性在創建基本布局上是特別有用的。而一旦你開始用 flexbox 創建網站的時候,你需要對其進行深挖以最大化地發揮它的價值。
現在我們來深入探討一下 flexbox 的縮放,并且學習如何利用它來構建適應性強而且漂亮的布局。
屬性1:flex-basis
上一篇文章中,主要介紹了應用在容器上的屬性。這次我們專門介紹如何在子元素進行縮放。
首先要介紹的第一個屬性在我看來可能是 flexbox 教程里面解釋的最少的屬性之一。
但是不要擔心,其實它很簡單。
flex-basis
控制的是一個元素的默認尺寸,但是它可以被flexbox 的其他屬性所影響(稍后會詳細介紹)。
下面這個 GIF 表示的是它和 width
屬性是可以互換的。

然而,flex-basis
和 width
不同的地方是,它是和 flex 坐標軸保持一致的。

flex-basis
是在主軸方向上影響元素大小的。
我們來看一下,當保持 flex-basis
不變的情況下,改變主軸方向,會發生什么。

這里要注意,原來設置的是 height
屬性,現在必須要手動地設置 width
屬性。flex-basis
根據 flex-direction
的不同會影響到 width
或者 height
。
屬性2:flex grow
接下來會有點復雜。
首先,把所有的方塊 width
都設置為120px:

現在來介紹一個屬性 flex-grow
,它的默認值是 0。意味著這些方塊不允許自動填充剩下的空間。
這又是什么意思呢?讓我們來看看,如果把各個方塊的 flex-grow
設置成 1 會發生什么:

所有方塊一起充滿了整個容器的寬度,并且它們之間的間隙也都是相同的,說明 flex-grow
覆蓋了 width
。
關于 flex-grow
讓人疑惑的地方在于它的值具體表達什么意思呢?flex-grow: 1
意味著什么呢?
為了解釋這個問題,我們把每個方塊的 flex-grow
值設置成 999,看一下效果:

可以看到,并沒有變化。
這是因為:flex-grow
并不是一個絕對值,而是一個相對值。
對于每個方塊來說,重要的不是 flex-grow
的值是多大,而是它的這個值和其他方塊的這個值相比較,相對大小是怎么樣的。
如果設置每個方塊為 flex-grow: 1
,然后逐漸改變第三個方塊的 flex-grow
,可以看到下圖的改變:

為了完全理解這個知識點,我們來快速簡單地來計算一下。
每個方塊 flex-grow
的起始值都是 1。把所有方塊的該值加起來,總和是 6。因此容器的總寬度被分成了 6 份。每個方塊就被擴展到容器所有可用空間的 1/6。
然后設置第三個方塊的 flex-grow
值為 2。那么容器的寬度被分成 7 等份,因為所有 flex-grow
屬性是:1 + 1 + 2 + 1 + 1 + 1。
第三個方塊占了整個容器空間的 2/7,其他的占了 1/7。
同理,當設置第三個方塊的 flex-grow: 3
的時候,整個容器寬度被分成了 8 份(1 + 1 + 3 + 1 + 1 + 1),第三個方塊占了 3/8,其他的占了 1/8。
以此類推。
flex-grow
只和比例相關,例如,設置第三個方塊 flex-grow: 12
,其余每個方塊的 flex-grow: 4
;跟第三個設置成 3,其他的設置成 1 得到同樣的效果,見下圖:

重點在于,每個方塊的 flex-grow
和其他方塊的是成比例的。
最后要注意的是,和 flex-basis
一樣,flex-grow
也是應用在主軸上的。除非把 flex-direction
設置為 column
,否則 flex-grow
只會影響方塊的寬度。
屬性3:flex shrink
flex-shrink
剛好和 flex-grow
相反,它是決定方塊收縮多少的。
它只應用于元素必須要縮小以適應容器的情況,即容器太小了。
它的主要用法是指定哪個元素你想要縮小,哪個不想縮小。默認情況是每個方塊都 flex-shrink: 1
,這表示每個方塊都會隨著容器的縮小而縮小。
我們來實戰中體會一下,在下面的 GIF 圖中,每個方塊的 flex-grow
都是 1,所以它們填滿了整個容器。每個方塊的 flex-shrink
也都是 1,所以它們也會像下面圖中這樣收縮。

接下來我們來設置第三個方塊的 flex-shrink
值為 0。不允許它收縮,所以它會隨著容器拉伸而拉伸,但是當容器收縮的時候,卻不允許比它的 120px 的width
還小。

flex-shrink
的默認值是 1,說明除非你特定地去設定這個值,否則元素都是默認收縮的。
同樣,flex-shrink
是和比例相關的。如果設置一個方塊的 flex-shrink
為 6,而其他的是 2,那么這個方塊隨著容器空間的壓縮,將以 3 倍于其他方塊的速度縮小。
這里尤其注意:是收縮的速度是 3 倍,而不是說它的寬度會縮小到原來的 1/3。
接下來準備更深入探討元素是如何收縮和拉伸的。不過在這之前,還需要介紹最后一個屬性,把這些東西都串起來。
屬性4:flex
flex
是 grow
,shrink
和 basis
的簡化形式——把它們所有都放到了一起。
它的默認值是:0(grow),1(shrink)和 auto(basis)。
我們把上一個例子簡化成只有兩個方塊,下面是它們的屬性:
.square#one {
flex: 2 1 300px;
}
.square#two {
flex: 1 2 300px;
}
兩個方塊都有著相同的 flex-basis
。也就是說如果有足夠的空間(容器的空間等于 600px 加上 margin 和 padding),它們的寬度將都會是 300px。
但是隨著容器的拉伸,方塊 1(有更大的 flex-grow
值)將會以兩倍的速度增長。隨著容器的收縮,方塊 2 (有更大的 flex-shrink
值)將會以兩倍的速度收縮。
都放到一起展示,如下圖:

元素是怎樣收縮和拉伸的呢
有些人可能會疑惑地發現:當方塊 1 拉伸時,并沒有拉伸到方塊 2 的兩倍大小。同樣,當方塊 2 縮小時,也并沒有縮小到方塊 1 的一半,盡管 flex-shrink
的比值是 2:1。
實際上這兩個屬性的意思,并不是說它們的大小是 2:1 或者 1:2,而是說它們的收縮率或拉伸率。
來點簡單的計算
容器的初始大小是 640px。在除去容器要預留的 20px 的 padding 后,剩下的空間足夠讓兩個方塊滿足 flex-basis
等于 300px。
當把容器設置為 430px 時,空間減小了 210px。方塊 1,設置了 flex-shrink
是 1,減小了 70px。而方塊 2,設置了 flex-shrink
是 2,減小了 140px。
當容器縮小到了 340px,容器空間減小了 300px。這時方塊 1 減小 100px,而方塊 2 減小 200px。
整體減小空間的分配方式,是按照各自設置的 flex-shrink
比例分配的(2:1)。
對于 flex-grow
也一樣。當容器拉伸到 940px 時,整體增加了 300px,方塊 1 增加 200px,而方塊 2 增加 100px。
當涉及到 flex 屬性時,其實它們說的都是比例。

從上圖中,可以看到寬度是如何根據設置的比例變化的,其中的 delta (?) 表示和原始 flex-basis
相比的變化量。
結論
最后總結一下:flex-basis
指的是一個元素在發生縮放之前,沿著主軸方向的大小。flex-grow
指的是在元素拉伸時,和兄弟元素相比的拉伸比例。flex-shrink
指的是在元素收縮時,和兄弟元素相比的收縮比例。
我們還有幾個 flexbox 屬性要講,請留意隨后幾周的文章。
我最近正在寫一本《React.js 小書》,對 React.js 感興趣的童鞋,歡迎指點。