前面我們學習到了 flexbox 布局。通過使用 flexbox 布局,我們可以更輕松實現以往很難實現的頁面布局。本文主要講解 flexbox 布局是如何去分配和計算布局剩余空間的。(本文閱讀前要求你對 flexbox 已經有了初步的認知,如果不是很了解,建議先學習前面視頻內容。)
基礎概念
為了更好地理解本文內容,我們需要先了解下面一些基礎概念。
flexbox 容器 (flexbox container)
flexbox 容器又稱彈性容器,通過設置 display: flex
而產生,簡單示例如下:
.container { display: flex; /* 或者 inline-flex */ }
flexbox 項目 (flexbox item)
當設置一個元素為 flexbox 容器時,其直接子元素將自動成為容器成員,也可以稱之為:flexbox 項目。
注:因為 flexbox 布局是發生在父元素和子元素之間的,所以下面為了行文方便,統一將 flexbox 容器稱為“父容器”,而 flexbox 項目統一稱為“子元素”
剩余空間
剩余空間就是指父容器在主軸方向上剩余未分配的空間,它是 flexbox 布局中一個很重要的詞。我們可以借助下面的例子來更好地理解:
<div class="container" width="600px" style="display:flex;"> <span class="item1" width="200px">item1</span> <span class="item2" width="200px">item2</span> </div>
上面代碼,我們定義了一個寬度為600px的父容器 container,以及寬度為200px的子元素 item1 和 item2 ,那么我們得出其剩余空間為200px,計算公式為:
剩余空間 = 父容器的寬度 - item1的寬度 - item2的寬度
剩余空間分配相關屬性
flexbox 布局中的子元素可以通過設置 flex
屬性來改變其所分配到的空間大小。flex
屬性包括了 flex-basis
、 flex-grow
、flex-shrink
flex-basis
flex-basis 用來定義子元素的默認寬或高。如果父容器 flex-direction
屬性的方向為水平方向則為寬度,如為垂直方向則為高度。相當於給子元素設置寬或高。如果同時設置了該屬性與寬或高,則該屬性權重大於寬或高的值。
flex-grow
flex-grow 用來指定父容器多余空間的分配比率,默認值為0。看到這里,大家可能還是沒有概念。為了更形象地理解,我們一起看下下面的例子。
例子: 只設置 item1 的 flex-grow 為1
其 HTML 代碼如下:
<div class="container"> <span class="item item-flex-grow">item1</span> <span class="item item2">item2</span> </div>
其 CSS 代碼如下:
/* css 部分 */ .container { display: flex; width: 600px; height: 140px; align-items: center; background-color: #ddd; } .item { width: 200px; height: 120px; line-height: 120px; text-align: center; background-color: orange; } .item2 { background-color: green; } .item-flex-grow{ flex-grow:1; background-color: }
這里我們對 item1 設置flex-grow:1
后,我們可以看到 item1 的所占空間寬度變成400px,也就是說 item1 把之前我們所說的父容器剩余的200px空間都占用了。
在這里我們可以得出:其實 flex-grow 即定義如何去分配父容器的剩余空間 ,當值為0時,則子元素都不會索取父容器的剩余空間。當 item1 設置 flex-grow: 1
的時候,由於 item2 沒有設置 flex-grow 的值,則剩余空間將會被分成一份,並且分別分給了 item1。
例子: 設置 item1 的 flex-grow 為1,且 item2 的 flex-grow 為3
如果此時我們設置 item2 的flex-grow:3
,item2 也將會參與索取父容器的剩余空間,此時父容器的剩余空間將分為4份,然后1份分配到 item1,而分配3份到 item2,如下圖:
如果子元素的寬度的總和超過父容器,flex-grow 將不生效。
上面的例子,我們只考慮了子元素的寬度總和都是沒有超過父容器的寬度的情況,則其可以使用 flex-grow 來分配父容器的剩余空間。那么當子元素的寬度總和超過父容器的寬度時,這時剩余空間還可以分配嗎?此時 flex-grow 是否還有效呢?讓我們先看看下面的例子:
這里我們設置上面例子的 item1 和 item2 的寬度為350px,則子元素的寬度總和為700px且超過父容器container的600px寬度。
我們可以看到 flex-grow 並沒有起到作用,且兩個 item 的寬度還被壓縮到只有300px。
通過之前學到的如何計算剩余空間的方法,我們可以算出本例子的剩余空間為600px - 700px即 -100px,這里可以得出由於沒有剩余空間,則定義了 flex-grow 的子元素能分配到的空間為0,故不生效。另外我們需要知道的是 flexbox 環境的父容器的寬度600px並不會因為子元素的總寬而改變,即子元素的寬度總和最多等於父容器的寬度,所以為了讓子元素完整顯示在父容器內,只有兩個辦法:
- 通過設置 flex-wrap 來使子元素換行
- 通過壓縮子元素來使其能容納在父容器內
flex-shrink
flex-shrink 用來指定父容器空間不夠時子元素的縮小比例,默認為1。如果一個 flexbox 項目的 flex-shrink 屬性為0,則該元素不會被壓縮。
為什么需要 flex-shrink 來定義縮小比例呢?
上面我們可以知道,當子元素的寬度總和大於 flexbox 父容器的寬度時,其剩余空間將為負數,如果沒有設置換行的情況下,其將會通過壓縮子元素來使其能夠容納在父容器內。那么我們如何控制子元素的壓縮比例呢?答案就是通過將通過設置 flex-shrink
這個屬性。
例子:設置項目的flex-shrink
下面例子,我們設置兩個 item 的寬度為350px,而容器 container 的寬度仍為600px。同時定義了 item1 和 item2 的 flex-shrink 的屬性分別為1和4。如下所示:
代碼如下:
/* 這里只展示關鍵css */ .container { display: flex; width: 600px; height: 140px; } .item { width: 350px; height: 120px; } .item1 { flex-shrink: 1; } .item2{ flex-shrink: 4; }
我們看到由於缺少100px的空間,按照 item1 和 item2 定義的 flex-shrink 的值,缺少的100px將分成5份。item1 將壓縮其中的 1/5 即20px,item2 的將壓縮其中的 4/5 即80px。
例子:設置項目的 flex-shrink 為0
在上面的知識中,我們了解到 flex-shrink 默認值為1,即默認子元素在父容器空間不足時會被壓縮。現在我們把項目的 flex-shrink 設為0來看下不壓縮的情況。如下所示:
代碼如下:
/* 這里只展示關鍵css */ .container { display: flex; width: 600px; height: 140px; } .item { width: 350px; height: 120px; flex-shrink: 0; }