[CSS] Flexbox 排版模式

什麼是 Flexbox Model?

這是一個 CSS3 才出現的規範,Flexbox 引進了新的排版模式,解決元素分佈不均、空白等距無法自動均分的現象。所以透過 Flexbox,對於若即使無法得知 viewport 或子元素大小的寬度時,可以透過 Flexbox 的相關設定,來讓子元素自動排列,就不再需要手動去計算相關間距了。

Flexbox Model 起手式

讓我們先看一個簡單的 html 結構:

<ul>
  <li>第一項</li>
  <li>第二項</li>
  <li>第三項</li>
</ul>

這只是一個很簡單的 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>

共有六種屬性可以設定,讓我來一一解說

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-direction> <flex-wrap>;
}

說明: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 相關屬性,此例為 <li>

共有六種屬性可以設定,以下一一解說

ul > li{
  // 第一種
  order: <number>; // 預設值是 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 || <positive number>; // 預設值是 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 || <positive number>; // 預設值是 1
}

說明:設定讓該 Flex Item 當有多餘空間時,是否要設定成「不要自動填滿」,預設值是 1,也就是 flex-shrink:1; ,不要自動填滿,其實就是代表將此功能開啟。這也是為什麼在預設狀況下, Flex Item 不會自動填滿多餘空間的原因。

ul > li{
  // 第四種
  flex-basis: auto || <percentages> || <ems> || <rems> || <pixels> etc; // 預設值是 auto
}

說明:flex-basis 是用來設定 Flex Item 的寬度,單位可以是任何百分比、em、rem、px等,預設值是 auto。也就是預設情況下,Flex Item 的寬度是會依據內容來自動變寬,例如下圖:

但若我加上以下:

ul > li:first-child{
  flex-basis: 100px;
}

就會變成如下圖了,也就是第 1 個 li 被限定 100px:

ul > li{
  // 第五種
  flex: <flex-grow> <flex-shrink> <flex-basis>; // 預設值依序是 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: <position number>; 代表的是 flex: <positive number> 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,如圖:

 

您可在此處留言

avatar

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料

  Subscribe  
Notify of