掌握 Flexbox,讓佈局簡單又有趣

今天要介紹 CSS 中的 Flexbox 佈局的基本特性。這是每個前端開發者都應該掌握的技能之一。這篇文章會帶你一步步了解 Flexbox 的基本概念和應用,讓你能夠在實際開發中靈活使用。

為什麼需要 Flexbox?

在過去,我們常常使用 floatinline-block 等方式來佈局網頁,這些方法雖然能解決部分問題,但往往需要寫很多額外的 CSS。而 Flexbox 專為佈局設計,使我們可以更簡單、高效地完成各種佈局需求。

Flexbox 基本概念

Flexbox 由兩個主要部分組成:容器(container)和項目(items)。我們首先需要將一個元素設置為 Flex 容器,然後它的直接子元素就會成為 Flex 項目。

Flex 容器

要將一個元素設置為 Flex 容器,只需給它設置 display: flex

1
2
3
4
5
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
1
2
3
4
5
6
7
8
9
10
.container {
...
width: 700px;
display: flex;
}

.item {
...
width: 100px;
}

容器內的每個子元素都是 Flex 項目,這些項目會自動排列成一行。

如果父元素有設定高度,那麼容器內的子元素的高度會跟著父元素的高度變動,除非另外設定 paddingmargin 或高度。

如果父元素沒有設定高度,而是其中一個或多個子元素設定了高度,或是裡面的元素把子元素撐開,那其他未設定高度的子元素會隨著最高的那個兄弟姊妹變動。如圖:

所有物件中只有`.item1` 和 `.item2` 設定了高度,而其他未設定高度的 item 則是跟著最高的 `.item2` 同高。

決定 flexbox 走向的軸線

flexbox可以做到讓元素橫向對齊、縱向對齊、等比排列等多種彈性佈局。要更透徹理解flexbox如何運作,在介紹它各種屬性前,不得不先了解一下它的兩根相互垂直的軸線——主軸(main axis)交叉軸(cross axis)

主軸由 flex-derection 定義,決定是元素是水平或是垂直排列,還有是否為反向排列。它的預設是水平排列。(下面會列出它的選項)。補充:如果使用的語言是像英文中文等從左到右的語言,則默認起始順序也是從左到右;但若是阿拉伯語等從右到左的語言,默認起始順序會是從右到左。

而交叉軸垂直於主軸,所以會根據主軸是橫向或縱向而決定。

align-items 就是控制交叉軸對對齊方式,預設是 stretch 拉伸。這就是為什麼上面的例子會介紹到在未設定子元素(交叉軸的)高度的情況下,子元素們的高度會自動拉伸填滿父容器,因為這就是交叉軸的預設值。

這是主軸和交錯軸都是默認值的樣子

把主軸轉為縱向排列,交叉軸則對應轉為橫向的。

容器屬性

flex-direction

flex-direction 決定了項目在容器中的排列方向。默認情況下,項目會水平排列(row)。

1
2
3
.container {
flex-direction: row; /* 可選 row(水平)、row-reverse(反向水平)、column(垂直)、column-reverse(反向垂直) */
}

justify-content

justify-content 用來控制項目在主軸(默認為水平軸)上的對齊方式。

1
2
.container {
justify-content: center; /* 可選 flex-start(左對齊)、flex-end(右對齊)、center(居中)、space-between(兩端對齊,項目之間均勻分布)、space-around(項目均勻分布,周圍留有空間) */

align-items

align-items 控制項目在交叉軸(默認為垂直軸)上的對齊方式。

1
2
3
.container {
align-items: center; /* 可選 flex-start(頂端對齊)、flex-end(底端對齊)、center(居中)、baseline(基線對齊)、stretch(拉伸填充) */
}

flex-wrap

默認情況下,所有項目會在一行內排列。如果希望項目換行,可以使用 flex-wrap。預設為不換行。

1
2
3
.container {
flex-wrap: wrap; /* 可選 nowrap(不換行)、wrap(換行)、wrap-reverse(反向換行) */
}

flex-flow

flex-flowflex-directionflex-wrap 的簡寫形式。

1
2
3
.container {
flex-flow: row wrap; /* 水平排列,並允許換行 */
}

align-content

當有多行項目時,align-content 用來控制這些行在交叉軸上的對齊方式。

1
2
3
.container {
align-content: center; /* 可選 flex-start、flex-end、center、space-between、space-around、stretch */
}



其他較為進階的項目屬性

order

order 用來控制項目的排列順序。默認情況下,所有 items 的 order 值都是 0,即按照源代碼順序呈現。更詳細說明參考 https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_flexible_box_layout/Ordering_flex_items

1
2
3
.item {
order: 1; /* 數值越小,項目越靠前 */
}

flex-grow

flex-grow 定義了 items 的擴展比率。默認值為 0,表示 items 不會放大。

前面提到 flex 特性是在不特別設定尺寸的情況下,或是當所有的子元素都有相同的flex-grow 系數時,子元素在空間分配上是相等的。

如果加了 flex-grow 就會在父元素有空間剩餘的時候,重新分配元素們的比例。它通常與以下提到的flex-shrinkflex-basis 共用,一起寫在flex 裡。

1
2
3
.item {
flex-grow: 1; /* 數值越大,項目擴展空間越多 */
}

flex-shrink

flex-shrink 定義了項目的收縮比率。默認值為 1,表示項目會收縮以適應容器大小。

提醒:flex-shrink 只在子元素加總的寬度超出父容器的情況下起作用;而縮減的比例是從多出來的那一段來分配,目的是讓所有子元素與父容器寬度相同。

1
2
3
.item {
flex-shrink: 1; /* 數值越大,項目收縮空間越多 */
}

flex-basis

flex-basis 定義了項目的基礎大小。可以先理解為主軸的寬/長度;如果前面有定義父容器主軸的寬/長度的話則會被flex-basis 蓋掉。

1
2
3
.item {
flex-basis: 100px; /* 可以設置具體大小或百分比 */
}

flex

flexflex-growflex-shrinkflex-basis 的簡寫。

1
2
3
.item {
flex: 1 1 100px; /* 1 表示擴展比率,1 表示收縮比率,100px 表示基礎大小 */
}

講這麼多,當然還是實作最能了解透徹,分享幾個相關的網站邊玩邊體會看看:

釐清概念用 -

六角提供的用起來非常清楚:https://codepen.io/peiqun/pen/WYzzYX

https://demo.agektmr.com/flexbox/

https://codepen.io/justd/pen/yydezN

練習用 -

沒錯又是六角做的小遊戲:https://hexschool.github.io/flexbox-pirate/index.html#/

這個很可愛:https://flexboxfroggy.com/

Flexbox 是一個非常強大的工具,能夠讓我們更輕鬆地實現各種佈局需求。在實際項目中靈活應用這些技巧,讓你的網頁佈局更加簡單高效。

快去玩玩上面分享的網站~越早熟悉它,越早體驗到排版的樂趣 ◍•ᴗ•◍