學習 Flexbox 版面配置

Flexbox 是 CSS3 裡一個比較特殊的版面設計模式。最初被設計出來的主要原因是為了提供更有效率的方式來完成傳統 CSS 無法輕易達成的效果 (例如垂直置中)。 Flexbox 適用於小區塊的版面使用,因此,整體版面結構還是建議用傳統的 Grid 模式做調整。本文將簡介目前最新標準的 Flexbox 語法。參考與圖片來源為:

為什麼要學 Flexbox

由於 Flexbox 的規範從 2009 年發布到 2012 年間經歷了許多變動,導致許多瀏覽器的支援性不佳,也讓開發者遲遲不敢使用這個技術。不過幸運的是,目前的規範已趨於穩定,而 Flexbox 也能有效地解決許多切版問題,各家的瀏覽器也開始比較有規範的支援。更重要的是,前一陣子才宣布的 React Native 就是使用 Flexbox 作為切版基底。也就是說,未來想透過 React Native 來寫 mobile app 的開發者或多或少都需要了解一點 Flexbox。

基礎概念

Flexbox 不同於其他單一的 CSS 屬性,它有專屬它自己的一些屬性和抽象概念。主要可分為兩大類:

想要將一個 HTML 元素設定為 Flex container 相當容易,你只需要在元素中加入 display: flexdisplay: inline-flex 。兩者的差別類似 display: blockdisplay: inline-block 的差別。所有在 Flex container 內的子元素就是 Flex item。如下圖:

Flexbox concept from TreeHouse

在圖中可觀察到的另一個重要觀念就是 Flexbox 是以兩個主軸為基礎,main axis 與 cross axis。這邊先大致說明一下圖中的各個關鍵字:

在 Flexbox 裡,所有元素的位置都是相對於上面所述的兩個主軸。隨著方向改變,所有的 flex item 位置也會有所變化。

Flex Container 屬性介紹

flex-direction

Flex Direction concept from TreeHouse

此屬性決定了 main axis 的方向,也代表著所有 flex item 的內容會如何排列。

.container {
    flex-direction: row | row-reverse | column | column-reverse;
}

flex-wrap

Flex Wrap concept from TreeHouse

Flexbox 預設會將所有 Flex item 都排列在同一排,此屬性可讓 flex container 在同一排塞不下所有 item 時產生換行效果。

.container{
    flex-wrap: nowrap | wrap | wrap-reverse;
}

flex-flow

flex-flow 屬性是 flex-directionflex-wrap 的縮寫,可快速定義 flex container 的主軸。預設為 row nowrap 。寫法如下:

.container{
    flex-flow: <flex-direction> || <flex-wrap>
}

justify-content

Justify-content concept from TreeHouse

justify-content 是用來定義 flex item 在 main axis 上的排列位置。它會依照賦予的值分配多餘的空白空間。

.container {
    justify-content: flex-start | flex-end | center | space-between | space-around;
}

align-items

align-items concept from TreeHouse

此屬性是用來定義 flex item 在 cross axis 上的排列位置。你可以這樣想:cross axis 與 align-items 的關係就像 main axis 與 justify-content之間的關係。

.container {
    align-items: flex-start | flex-end | center | baseline | stretch;
}

align-content

align-content concept from TreeHouse

align-content 主要是用在當 main-axis 有換行時。此屬性相當於 justify-contentalign-items 的綜合版,不過它排列的是整個內容,而不是單一行。排列對應的軸是 cross axis 而非 main-axis。注意:當 main axis 沒換行時,此屬性不會有作用。

.container {
    align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}

Flex Item 屬性介紹

所有包在 Flex Container 內的直接子元素都是 Flex item,包含文字。floatclearvertical-align對 Flex item 沒有作用。Flex item 內的元素與內容不會被 Flexbox 影響。舉個例子:在 Flex item 元素上加入 float: left 不會有任何反應,但在 Flex item 的子元素裡加入 float: left 則會正常往左浮動。

order

order concept from TreeHouse

order 是一個非常好用的屬性,它賦予了我們不用修改 HTML 就能更動元素位置的能力。一般來說,每個 item 都是依照在 HTML 中的排列順序出現,但此屬性可控制元素出現的先後順序。值越小的排越前面。

.item {
    order: <integer>;
}

flex-grow

flex-grow concept from TreeHouse

此屬性賦予每個 item 在需要時自動佔滿剩餘寬度的能力。接受的值為一個無單位的數字,此數字決定了 item 在剩餘的空間內該佔滿多少比例的寬度。如果所有的 item 都將 flex-grow 設為 1,那麼每個 item 都會有相同寬度並佔滿所有空間。如果將其中一個的 flex-grow 改為 2 的話,被修改的元素將會佔滿比其他元素兩倍大的空間。

.item {
    flex-grow: <number>; /* default 0 */
}

flex-shrink

此屬性為 flex-grow 的相反。

.item {
    flex-shrink: <number>; /* default 1 */
}

flex-basis

此屬性會依照 flex-direction 定義 item 最小的寬度或高度,有點類似 min-width。這個屬性可以翻譯成:當需要伸縮時,依照 flex-growFlex-shrink 的值來伸縮,但是寬度或高度不能小於 X px 或 em。

.item {
    flex-basis: <length> | auto; /* default auto */
}

flex

flex 屬性是 flex-growflex-shrinkflex-basis 的縮寫,第二和第三個參數 (flex-shrinkflex-basis) 可不給。預設值為 0 1 auto

.item {
    flex-basis: <length> | auto; /* default auto */
}

建議使用此屬性而非獨立使用上述三個屬性來設定 item 寬/高度。

align-self

align-self concept from TreeHouse

此屬性可以將個別 item 的 align-items 屬性覆蓋過去進而提供更為彈性的設計模式。

.item {
    align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

對於此屬性的值的解說,請參考 align-items 部分。

總結

Flexbox 是一個非常強大的排版模式,它輕易的解決了以往許多需要使用各種怪異的方法來解決的問題。但,它的整體架構與常見的 Grid 系統又不太一樣,開發者需要換一個角度來思考版面的配置。希望這篇文章有讓大家準備好在未來的專案裡使用 Flexbox。如果文章內有任何問題,也歡迎各位討論糾正。

profile-image
Hello, I'm Rhadow. A software engineer curious about how nature works. Dreaming to simulate our world in computer one day.
comments powered by Disqus