初識 CSS 排版大師 Flexbox (一)

初識 CSS 排版大師 Flexbox (一)

在從 table 轉往 div 排版的過程中,編排一個需要彈性等高的田字形的 Layout,或是要將內容垂直置中,一定曾在某個時刻讓人心碎過。這種 Layout 用 table 很容易達成,但改成 DIV 的方式卻又很費心,甚至有時還得來點 JS 才能解決,對視覺設計師來說,實在很討厭。

囧
所幸,到了 CSS3 的時候,迎來了一個新的 Display 屬性 Flex,可以用來滿足彈性佈局的需要,上述的問題才終於有一個比較省心的解決方式。下面我們就簡單地介紹一下 FLexbox 這個新朋友。

先複製下面的 HTML

這是一個 html 範例,也是很常見的佈局場景,內容長短不盡相同,接下來會以它當例子:)

<ul class="box">
  <li>content content content content content content content content content content content content content content content content content content content content content content content content </li>
  <li>content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content </li>
  <li>content content content content content content content content content content content content content content content content content content </li>
  <li>content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content </li>
  <li>content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content </li>
  <li>content content content content content content content content content content content content </li>
  <li>content content content content content content content content content content content content content content content content content content </li>
</ul>

傳統的做法

過去我們在處理佈局的時候,多半會採用 float、display、position 等等 CSS 屬性,在沒有經過特別處理的情況下,區塊與區塊之間會有長短不一的情況,垂直置中也很困難。如果要強制設定區塊的高度,又需要考量內容的來源很難掌握的問題,像是部落格的文章列表,過多或過少的內容都會影響頁面 Layout 編排的整齊,你也很難去限制使用者該輸入多少內容,這是傳統編排上令人頭痛的地方。

下面是一個例子:

<style type="text/css">
html,body{background:#333;}
ul.box, ul.box li{display:block; margin:0; padding:0; list-style: none;}
ul.box{width:800px; background:#222;}
ul.box li{
  display:inline-block;
  background:#fff;
  width:30%;
}
ul.box li:nth-child(odd){background:#ccc;}
ul.box li:nth-child(1){background:blue; color:#fff;}
ul.box li:nth-child(2){background:red; color:#fff;}
ul.box li:nth-child(3){background:green; color:#fff;}
</style>

改成 Flexbox (Flexible Box) 後

Flexbox 主要的用途在於透過配置元素內的寬、高及位置,對頁面的 Layout 進行更有效的編排,讓過去使用 block box 模型的一些缺點,能透過 Flexbox 來解決。

其屬性如下:

最基本的 Flexbox 是指定一個元素容器為 display:flex,意為這是一個彈性的 box 模型,而其下包含一個以上的子元素。每個子元素皆為 Flex item。

以我們的案例來說,當 ul 設定成 display:flex;,被 ul 包圍的 li 會變成 flex item 排列成一行,且會依據父元素 ul 的寬度自動調節 li 子元素的寬度及自動等高,因為我們還沒有設定 flex-wrap,他在預設的情況是 nowrap,也就是不斷行,這時就算你指定 flex item 的寬度,也會被忽略掉。如下例:

<style type="text/css">
html,body{background:#333;}
ul.box, ul.box li{display:block; margin:0; padding:0; list-style: none;}
ul.box{
  width:800px;
  background:#222;
  display:flex;
}
ul.box li{
  background:#fff;
  width:30%;
}
ul.box li:nth-child(odd){background:#ccc;}
ul.box li:nth-child(1){background:blue; color:#fff;}
ul.box li:nth-child(2){background:red; color:#fff;}
ul.box li:nth-child(3){background:green; color:#fff;}
</style>

flex-wrap:讓 flex item 折行

如果你希望設定 flex item 的寬度,並希望當 flex item 的寬度總和大於父元素寬時,flex item 可以自動往下堆疊,這時我們需要另外設定 flex-wrap:wrap;,另外需要注意的是,當你設定 flex-wrap:wrap; 的時候,flex item 需同時設定寬度,這樣 flex-wrap:wrap; 才會知道折行的斷點在哪裡。

flex-wrap 其他選擇如下

  • flex-wrap:nowrap; 不折行,預設值
  • flex-wrap:wrap; 折行,並置頂
  • flex-wrap:wrap-reverse; 折行,並置底
  • flex-wrap: initial; 初始值
  • flex-wrap:inherit; 繼承父值

W3Schools 有一個 flex-wrap 線上實作的範例,你可以自己動手玩看看。

下面是一個範例:

<style type="text/css">
html,body{background:#333;}
ul.box, ul.box li{display:block; margin:0; padding:0; list-style: none;}
ul.box{
  width:800px;
  background:#222;
  display:flex;
  flex-wrap:wrap;
}
ul.box li{
  background:#fff;
  width:30%;
}
ul.box li:nth-child(odd){background:#ccc;}
ul.box li:nth-child(1){background:blue; color:#fff;}
ul.box li:nth-child(2){background:red; color:#fff;}
ul.box li:nth-child(3){background:green; color:#fff;}
</style>

justify-content:水平置中

如果你希望子元素水平置中於父元素,只需要對父元素指定 justify-content:center;,justify-content 還可以設定

  • justify-content:flex-start; 水平置左
  • justify-content:flex-end; 水平置右
  • justify-content:center; 水平置中
  • justify-content:space-between; 分散對齊
  • just-content:space-around; 平均對齊

範例如下:

<style type="text/css">
html,body{background:#333;}
ul.box, ul.box li{display:block; margin:0; padding:0; list-style: none;}
ul.box{
  width:800px;
  background:#222;
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
}
ul.box li{
  background:#fff;
  width:30%;
}
ul.box li:nth-child(odd){background:#ccc;}
ul.box li:nth-child(1){background:blue; color:#fff;}
ul.box li:nth-child(2){background:red; color:#fff;}
ul.box li:nth-child(3){background:green; color:#fff;}
</style>

align-items:傳說中的垂直置中 (撒花)

如果你希望 flex item 可以垂直置中的話,可以使用 align-items:center,我們終於可以在 CSS3 裡,透過簡單的屬性設置來完成它。(感動莫名…p___q…)

align-items 中比較特別的是 baseline,一般人可能比較難理解它的意思,只會猜測是某個東西的基準線。但如果你對字型設計有概念的話,會立刻聯想到 baseline 指的是多數字母排列的基準線,如下圖紅線的位置。


基線 (baseline)

這裡的 baseline 指的是對齊 flex item 的第一行文字的基線,如果你希望看的看得清楚一點的話,可以將 flex item 裡的文字設置成不同的尺寸,或者看看我們的範例

align-iteams 還可設置為:

  • align-items:stretch; 撐滿天地,預設值
  • align-items:flex-start; 垂直置頂
  • align-items:flex-end; 垂直置底
  • align-items:center; 垂直置中
  • align-items:baseline; 對齊文字的基準線
  • align-items:initial; 初始值
  • align-items:inherit; 繼承父值

W3Schools 有一個 align-items 線上實作的範例,你可以自己動手玩看看。

下面是一個範例:

<style type="text/css">
html,body{background:#333;}
ul.box, ul.box li{display:block; margin:0; padding:0; list-style: none;}
ul.box{
  width:800px;
  background:#222;
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  align-items:center;
}
ul.box li{
  background:#fff;
  width:30%;
}
ul.box li:nth-child(odd){background:#ccc;}
ul.box li:nth-child(1){background:blue; color:#fff;}
ul.box li:nth-child(2){background:red; color:#fff;}
ul.box li:nth-child(3){background:green; color:#fff;}
</style>

flex-direction:改變排列的方向

如果你希望調整 flex item 排列的方向,你可以透過 flex-direction 來改變,flex-direction 的選項有:

  • flex-direction:row; 預設值,由左至右,由上到下
  • flex-direction:row-reverse; 由右至左,由上到下
  • flex-direction:column; 直排
  • flex-direction:column-reverse; 與 column 顛倒過來
  • flex-direction: initial; 初始值
  • flex-direction: inherit; 繼承父值

W3Schools 有一個 flex-direction 線上實作的範例,你可以自己動手玩看看。

下面是一個範例:

<style type="text/css">
html,body{background:#333;}
ul.box, ul.box li{display:block; margin:0; padding:0; list-style: none;}
ul.box{
  width:800px;
  background:#222;
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  align-items:center;
  flex-direction:row-reverse;
}
ul.box li{
  background:#fff;
  width:30%;
}
ul.box li:nth-child(odd){background:#ccc;}
ul.box li:nth-child(1){background:blue; color:#fff;}
ul.box li:nth-child(2){background:red; color:#fff;}
ul.box li:nth-child(3){background:green; color:#fff;}
</style>

order:自定排序

如果你想要自己排序的話,可以在 flex item 中設置 order,參數為數值,以我們的案例來說,共有 7 個 flex item,所以在設定的時候,我們有 1-7 可以選擇。

下面是一個範例:

<style type="text/css">
html,body{background:#333;}
ul.box, ul.box li{display:block; margin:0; padding:0; list-style: none;}
ul.box{
  width:800px;
  background:#222;
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
}
ul.box li{
  background:#fff;
  width:30%;
}
ul.box li:nth-child(odd){background:#ccc;}
ul.box li:nth-child(1){background:blue; color:#fff; order:4;}
ul.box li:nth-child(2){background:red; color:#fff; order:7;}
ul.box li:nth-child(3){background:green; color:#fff; order:2;}
ul.box li:nth-child(4){order:1;}
ul.box li:nth-child(5){order:3;}
ul.box li:nth-child(6){order:5;}
ul.box li:nth-child(7){order:6;}
</style>

結論:

整體來說,flexbox 解決了 block box 模型使用上的一些問題,提供一個更具有彈性的解決方式,讓我們在編排版面的時候,可以透過參數的調整擁有更多的選擇,省去一些內容導致區塊內長短腳的問題,增加版面的靈活及整齊。

文章到此差不多要告一段落了,希望這篇文章對你有所幫助,如果你有什麼建議或是疑問的話,也可以透過下面的留言系統與我們討論,Bye~

每個人的生命都有一些重要的東西,對我而言,網路、單車、相機和繪畫一直在生命中的某些時刻扮演著重要的角色。我不明白老天爺是否要透過這些東西的集合告訴我什麼。只能努力地去串連這些看似無關的事物,並試著藉此為生活塗上一些屬於個人的顏色與符號。在自我追尋的同時,也期許能夠豐富這個世界。

2 Comments

  1. Quby · 2017-04-15 Reply

    flexbox 頗複雜, 可以搭配線上測試工具來學: http://loading.io/flexbox

你的觀點