什麼是 Flexbox Model?
這是一個 CSS3 才出現的規範,Flexbox 引進了新的排版模式,解決元素分佈不均、空白等距無法自動均分的現象。所以透過 Flexbox,對於若即使無法得知 viewport 或子元素大小的寬度時,可以透過 Flexbox 的相關設定,來讓子元素自動排列,就不再需要手動去計算相關間距了。
Flexbox Model 起手式
讓我們先看一個簡單的 html 結構:
- 第一項
- 第二項
- 第三項
這只是一個很簡單的 ul 結構,如果今天不加上任何 css 樣式,它的呈現會如下圖:
這時我想宣告 ul 為 Flexbox Model 模式,那麼 CSS 語法就需要寫成(有額外增加樣式的調整,主要是以下的藍字及綠字):
ul{ display: flex; /* 也可以是:display: inline-flex; 此為「行內 Flex」 */ padding:0; } ul > li{ list-style: none; }
這時結果如下圖:
發現裡面的 li 變成水平排列了,好,到這邊我們需要先瞭解幾件事情:
- ul 已經變成了 Flexbox Model 排版模式,會直接影響到其第一層子元素(Flex item(s))的排版行為。
- ul 是 Flexbox Model 中的 Flex container。
- li 是 Flexbox Model 中的 Flex item(s),因為是 ul 的第一層子元素。
- 此範例適用於任何父子元素,不僅限於 ul、li,也可以用在任何 div 或其它元素。
Flex Container 相關屬性,此例為
共有六種屬性可以設定,讓我來一一解說
ul{ // 第一種 flex-direction: row || column || row-reverse || column-reverse; }
這個屬性的設定有4個屬性值,要瞭解這四個屬性值,必須先瞭解 flexbox model 中的兩個軸: Main Axis 和 Cross Axis,請看下圖:
當 ul 設定為 display:flex 時,就代表會有這兩個隱形的軸,Main Axis 表示從左至右;Cross Axis 表示從上至下。
然而當 flex-direction 設定為以下的值時,就會影響到第一層子元素(Flex Items)的排列方向:
- row:這也是預設值,代表 Flex Items 會從左至右依序排列。
- column:代表 Flex Items 會從上至下依序排列。
- row-reverse:代表 Flex Items 會從右至左依序排列。
- column-reverse:代表 Flex Items 會從下至上依序排列。
ul{ // 第二種 flex-wrap: wrap || no-wrap || wrap-reverse; }
說明:
-
wrap:代表當 Flex Items 數量過多,多到 Flex Container 裝不下的時候,會斷行,會斷行的方向會是往下斷行。
-
no-wrap:此為預設值,代表即使 Flex Items 數量過多,依然不會斷行,Flex Container 都會試圖去包含這些 Flex Items 在同一列。
-
wrap-reverse:代表當 Flex Items 數量過多,多到 Flex Container 裝不下的時候,會斷行,會斷行的方向會是往上斷行。
ul{ // 第三種 flex-flow:} ;
說明:flex-flow 單純只是個 flex-direction 和 flex-wrap 同時用的縮寫,例如:flex-flow: row wrap-reverse;。
ul{ // 第四種 justify-content: flex-start || flex-end || center || space-between || space-around; }
說明:justify-content 是用來定義 Flex Items 該如何在 Main Axis 排列。例:
-
flex-start:這是預設值。代表 Flex Items 從 Main Axis 的起點開始排列。
-
flex-end:代表 Flex Items 整個的結尾要往 Main Axis 的尾端貼齊。
-
center:同上意義,只是要針對 Main Axis 來置中。
-
space-between:各個 Flex Item 延著 Main Axis 平均分散,但 Flex Item 之間,要保持相同距離。
-
space-around:各個 Flex Item 延著 Main Axis 平均分散,但每一個 Flex Item 周圍都要保持相同的距離。
另外以下這張圖更能清礎說明 space-around 的意義:
ul{ // 第五種 align-items: flex-start || flex-end || center || stretch || baseline; }
說明:align-items 與 justify-content 非常相似,只是是用來定義 Flex Items 該如何在 Cross Axis 排列。例:
-
flex-start:代表 Flex Items 高度並不會增加至 Flex Container 的高度,各 Flex Items 會直接對齊 Cross Axis 的起點。
-
flex-end:代表 Flex Items 高度並不會增加至 Flex Container 的高度,各 Flex Items 會直接對齊 Cross Axis 的最終點。
-
center:各 Flex Items 會直接對齊 Cross Axis 的中間。
-
stretch:這是預設值。代表 Flex Items 的高度,沿著 Cross Axis,都會自動增加高度至 Flex Container 的高度。
-
baseline:會依據 Flex Items 的 baseline 來對齊。
以下這張圖也許更能看出 baseline 的對齊方式:
ul{ // 第六種 align-content: flex-start || flex-end || center || stretch; }
說明:align-content 主要是用在 Flex Container 中的 Flex Items 產生多行時,那麼這些 Flex Item 該如何針對 Cross Axis 來排列。例:
-
flex-start:即使遇到 Flex Items 斷行,會沿著 Cross Axis 如下排列(置頂):
-
flex-end:即使遇到 Flex Items 斷行,會沿著 Cross Axis 會如下排列(置底):
-
center:即使遇到 Flex Items 斷行,會沿著 Cross Axis 會如下排列(置中):
-
stretch:這是預設值,即使遇到 Flex Items 斷行,各 flex-items 的高度會沿著 Cross Axis 自動增減。
Flex Item 相關屬性,此例為
共有六種屬性可以設定,以下一一解說
ul > li{ // 第一種 order:; // 預設值是 0 }
說明:order 可以是任何的整數,所有的 Flex Items 預設值都是0。然而所有的 Flex Items 的排列順序都會按照 order 值的大小來排列,從最小開始排,依序排到最大值。例如以下是都不設定的預設情況:
然後若我將第一個 li 的 order 設定成1,例:
ul > li:first-child{ order:1; }
那麼因為第 1 個 li 的值是當中最大的,其它 li 並沒有設定,所以預設值都是 0,所以從 order 的值最小到最大,所以第 1 個 li 會被排到最後,如圖:
ul > li{ // 第二種 flex-grow: 0 ||; // 預設值是 0 }
說明:設定讓該 Flex Item 會自行延展,將多餘空間給佔滿。然而 flex-grow 預設值都是 0,其實就是代表將此功能關閉。假設 ul 裡只有一個 li,預設的狀況下,會是如下圖:
也就是不會自動佔滿版面(因為預設值為 0),但如果我將 flex-grow 設定成 1,例:
ul > li:first-child{ flex-grow:1; }
ul > li{ // 第三種 flex-shrink: 0 || 1 ||; // 預設值是 1 }
說明:設定讓該 Flex Item 當有多餘空間時,是否要設定成「不要自動填滿」,預設值是 1,也就是 flex-shrink:1; ,不要自動填滿,其實就是代表將此功能開啟。這也是為什麼在預設狀況下, Flex Item 不會自動填滿多餘空間的原因。
ul > li{ // 第四種 flex-basis: auto |||| // 預設值是 auto }|| || etc;
說明:flex-basis 是用來設定 Flex Item 的寬度,單位可以是任何百分比、em、rem、px等,預設值是 auto。也就是預設情況下,Flex Item 的寬度是會依據內容來自動變寬,例如下圖:
但若我加上以下:
ul > li:first-child{ flex-basis: 100px; }
就會變成如下圖了,也就是第 1 個 li 被限定 100px:
ul > li{ // 第五種 flex:// 預設值依序是 0 1 auto; } ;
說明:flex 是縮寫,分別代表的是 flex-grow、flex-shrink、flex-basis。
雖然 flex 是個縮寫的語法,但有幾個觀念及好用的縮寫我們可以來記得:
- flex: 0 1 auto; 這是預設值。
- flex: default; 又是 flex: 0 1 auto; 的縮寫。
- flex: 1 1; 像這種 flex-basis 沒有指定的情況,flex-basis 的值會被設定成是 0,則該 Flex Item 就會被稱做是 Absolute Flex Item(表示該 Flex Item 的寬度,會依照 flex-grow 來分配寬度)。
- flex-basis: 100px; 像這種只有指定 flex-basis ,但沒有指定flex-grow 和 flex-shrink 的情況,則該 Flex Item 就會被稱做是 Relative Flex Item(表示該 Flex Item 的寬度會依據內容來決定)。
-
flex: 0 0 auto; 代表也將 flex-shrink 自動縮小的功能關閉,也可以寫成 flex:none; 。該 Flex Item 的寬度就會是內容寬,像這種狀況就極有可能會超過 Flex Container 的寬度,例如下圖(紅框是 ul 的寬度):
當螢幕寬度不夠時,就會有水平捲軸跑出來。 - flex: 1 1 auto; 代表也將 flex-grow 自動延展的功能開啟,也可以寫成 flex:auto; 。該 Flex Item 的寬度會自動計算,且會自動填滿 Flex Container 的多餘空間,有必要的話,寬度自動縮小(flex-shrink 是 1 的原因)。
-
flex:
; 代表的是 flex:1 0; 。所以當只寫 flex:2; 時,其實就是 flex: 2 1 0;。 -
承上,當第一個 li 的 flex-grow 是 2,第二個 li 的 flex-grow 是 1 的話,會發生什麼情況呢?就會按照比例來分配剩餘空間,第一個 li 會佔 2/3,第二個 li 會佔 1/3:
ul > li:nth-child(1){ // 第六種 align-self: auto || flex-start || flex-end || center || baseline || stretch; // 預設值是 stretch; }
說明:align-self 代表只會影響到特定的 Flex Item 針對 Cross Axis 它的排列方式而已,不會影響到其它的 Flex Items。預設值是 stretch。以下紅色背景是有針對 align-self 做的個別設定:
- auto:該 Flex Item 的值,會直接與 Flex Container 的 align-items 值一樣。
-
flex-start:該 Flex Item 會對齊 Cross Axis 的起點,高度不會自動擴展,如圖:
-
flex-end:該 Flex Item 會對齊 Cross Axis 的終點,高度不會自動擴展,如圖:
-
center:該 Flex Item 會對齊 Cross Axis 的中間,高度不會自動擴展,如圖:
-
baseline:有設定成 baseline 的這些 Flex Items ,會彼此對齊 baseline,如圖以下的第1個及第2個:
-
stretch:該 Flex Item 會自動擴展,佔滿整個 Flex Container,如圖: