Finally! I do understand "flex-basis"
Long, long, long ago,CSS3就支援了flex佈局,現在各家瀏覽器都支援標準的語法了,這裡推薦一篇比較全面的圖文化教程A Complete Guide to Flexbox.
關於Flex佈局,剛開始學習CSS的時候就"複習"了好幾遍,不是我吹,下面的程式碼也是信手拈來.
div {
display: flex;
justify-content: space-evenly;
align-items: center;
}
but,but,but.....,

flex佈局的伸縮子項上支援一個叫做flex-basis
的屬性.閱文件無數,我還是從始至終都沒怎麼理解.最近在寫自己的部落格主題flex: 1 1 300px
讓我重新想起了flex-basis
這個妖精,所以我決定這次一定要收了它.
MDN:flex-basisMDN文件對於此屬性的解釋如下
The flex-basis CSS property sets the initial main size of a flex item. It sets the size of the content box unless otherwise set with box-sizing.
翻譯過來就是:
CSS 屬性
flex-basis
指定了 flex子項元素在主軸方向上的初始大小。如果不使用 box-sizing 來改變盒模型的話,那麼這個屬性就決定了 flex 子項元素的內容盒(content-box)的寬或者高(取決於主軸的方向)的尺寸大小。
讀罷此句,似乎也不知道flex-basis
是用來幹什麼的,有人對這個屬性的使用進行了總結,下面的兩句是我認為最精華的兩點:
1.flex-basis allows you to specify the initial/starting size of the element, before anything else is computed. It can either be a percentage or an absolute value.
flex-basis
允許您在計算任何其他內容之前指定元素的初始/開始大小。它可以是百分比,也可以是絕對值。
2.flex-basis defines the default size of an element before the remaining space is distributed. It can be a length (e.g. 20%, 5rem, etc.) or a keyword.
flex-basis
定義在分配剩餘空間之前元素的預設大小。它可以是一個長度(例如20%,5rem等)或關鍵字
也許上面的解釋還是比較難懂,下面我們結合w3c的wiki文件中提供的一張圖來說明

我們都知道,flex佈局的最大的特點就是可以自定義如何分配容器剩餘的空間,或者壓縮子項來適應空間的不足.擴充套件比率是由flex-grow
設定的,收縮比率是由flex-shrink
設定的,伸縮基準是由flex-basis
設定的,三個屬性合併的寫法就是flex
屬性.如上圖,假設一個場景,伸縮容器的寬度是1000px,伸縮子項item1,item2,item3的width
分別是100px,400px;200px
.
<div id="container">
<div class="item1"></div>
<div class="item2"></div>
<div class="item3"></div>
</div>
div {
box-sizing: border-box;
}
#container {
display: flex;
box-sizing: content-box;
margin: auto;
width: 1000px;
height: 200px;
border: 2px solid orange;
font-size: 1.5rem;
color: white;
}
.item1 {
width: 100px;
background: red;
}
.item2 {
width: 300px;
background: green;
}
.item3 {
width: 200px;
background: blue;
}

子項的flex屬性預設值為flex: 0 1 auto
,即有剩餘空間時也不進行擴充套件,因此其預設的顯示如上圖.容器右側剩餘400px
的空間.接下來,我們給子項新增上擴充套件比率flex-grow
,讓子項按照1:1:2
的比率分配剩餘空間.
.item{
flex-basis: auto;
}
.item1{
width: 100px;
flex-grow: 1;
background: red;
}
.item2{
width: 300px;
flex-grow: 1;
background: green;
}
.item3{
width: 200px;
flex-grow: 2;
background: blue;
}

上述伸縮基準flex-basis: auto
,這個值會在瀏覽器分配空間時計算為元素在主軸方向上的長度屬性,此例子中即為子項的寬度.從上圖可以看出,剩餘空間按照100px: 100px: 200px
分別分配給了子項,子項在原有width
值上進行了這些疊加.這似乎符合我們常用的習慣,接下來,我們修改一處地方,將所有子項的伸縮基準設定為flex-basis: 0
.item{
flex-basis: auto;
}

從上圖可以看出實際展示寬度發生了天翻地覆的變化,我們來分析一下這個變化的原因.還記得文章一開始的重點嗎:
flex-basis定義在分配剩餘空間之前元素的預設大小
也就是說,當所有子項設定flex-basis: 0
,在分配空間的時候瀏覽器不再關注所有子項原有的寬度(準確的說是:子項在主軸方向的長度),這時剩餘寬度就是1000px - 0px -0px -0px = 1000px
,然後直接按照1:1:2
的比例分配1000px
,所以最終三個子項的寬度分別為: 200px, 200px, 400px
.
有一個很形象的例子可以解釋上述空間的分配,解放初期,我國進行過"人民公社化"的嘗試,假設有一個公社有三戶人家,三家各有糧食100kg, 300kg, 200kg
,三家各有1,1,2
口人,各家各戶把家裡的餘糧全部上交到公社食堂,縣裡又給公社撥了400kg
糧食,這樣各家的餘糧都是0,公社共有1000kg
的糧食,在食堂吃飯的時候,是按照各戶人口來分配食物的,所以三家分到的食物分別是200kg, 200kg, 400kg

有了上面的準則和介紹,下面的變化應該就能分析出來了.
.item1 {
width: 100px;
flex-grow: 1;
flex-basis: 200px;
background: red;
}
.item2 {
width: 300px;
flex-grow: 1;
flex-basis: 100px;
background: green;
}
.item3 {
width: 200px;
flex-grow: 2;
flex-basis: 300px;
background: blue;
}

在分配空間的時候,子項在主軸上的基準長度,由flex-basis
決定,也就是200px, 100px, 300px
,剩餘400px按照1:1:2
的比例分配,最後寬度200px+100px=300px, 100px+100px=200px, 300px+200px=500px
最後還有兩點需要注意:
1.flex-basis
影響的子項在主軸上的伸縮基準值,前面的例子我們預設的flex-direction: row
,如果flex-direction: column
也有學會以此類推.空間不足的時候子項需要的收縮情況也可以類比出來.
2.需要注意子項的長度還是會受到max-width/min-width
(當flex-direction: row
)或max-height/min-height
的影響,比如給最後一項新增一個max-width:400px
.item1 {
width: 100px;
flex-grow: 1;
flex-basis: 200px;
background: red;
}
.item2 {
width: 300px;
flex-grow: 1;
flex-basis: 100px;
background: green;
}
.item3 {
max-width: 400px;
width: 200px;
flex-grow: 2;
flex-basis: 300px;
background: blue;
}

因為第三項的最大長度是400px
,那就多出來100px
,前面兩項按照1:1
分配掉