別再用 float 佈局了,flex 纔是未來!

大家好,我是樹哥!

前面一篇文章整體介紹了 CSS 的佈局知識,其中說到 float 佈局是 CSS 不斷完善的副產物。而在 2023 年的今天,flex 這種佈局方式纔是未來!那麼今天我們就來學習下 flex 彈性佈局。

什麼是 Flex 佈局?

在經過了長達 10 年的發展之後,CSS3 才終於迎來了一個簡單好用的佈局屬性 —— flex。Flex 佈局又稱彈性佈局,它使用 flexbox 屬性使得容器有了彈性,可以自動適配各種設備的不同寬度,而不必依賴於傳統的塊狀佈局和浮動定位。

舉個很簡單地例子,如果我們想要實現一個很簡單左側定寬,右側自適應的導航佈局,如下圖所示。

-w1239

在沒有 flex 之前,我們的代碼是這麼寫的。

<div>
<h1>4.1 兩欄佈局 - 左側定寬、右側自適應 - float</h1>
<div class="container">
  <div class="left41"></div>
  <div class="right41"></div>
</div>
</div>
/** 4.1 兩欄佈局 - 左側定寬、右側自適應 - float **/
.left41 {
  float: left;
  width: 300px;
  height: 500px;
  background-color: pink;
}
.right41 {
  width: 100%;
  height: 500px;
  background-color: aquamarine;
}

這種方式不好的地方在於,我們還需要去理解 float 這個概念。一旦需要理解 float 這個概念,我們就會拖出一大堆概念,例如文檔流、盒子模型、display 等屬性(雖然這些東西確實應該學)。但對於 flex 來說,它就很簡單,只需要設置一個伸縮係數即可,如下代碼所示。

<div>
<h1>4.2 兩欄佈局 - 左側定寬、右側自適應 - flex</h1>
<div class="container42">
  <div class="left42"></div>
  <div class="right42"></div>
</div>
</div>
.container42 {
  display: flex;
}
.left42 {
  width: 300px;
  height: 500px;
  background-color: pink;
}
.right42 {
  flex: 1;
  width: 100%;
  height: 500px;
  background-color: aquamarine;
}

上面的代碼裏,我們只需要將父級容器設置爲 flex 展示形式(display: flex),隨後在需要自動伸縮的容器裏設置屬性即可。上面代碼中的 flex: 1 表示其佔據所有其他當行所剩的空間。通過這樣的方式,我們非常方便地實現了彈性佈局。

當然,上面只是一個最簡單的例子,甚至還不是很能體現出 flex 的價值。flex 除了在響應式佈局方面非常方便之外,它在對齊等方面更加方便,能夠極大地降低學習成本、提高工作效率。

Flex 核心概念

對於 Flex 佈局來說,其有幾個核心概念,分別是:主軸與交叉軸、起始線和終止線、Flex 容器與 Flex 容器項。

主軸和交叉軸

在 Flex 佈局中有一個名爲 flex-direction 的屬性,可以取 4 個值,分別是:

  • row
  • row-reverse
  • column
  • column-reverse

如果你選擇了 row 或者 row-reverse,那麼主軸(Main Axis)就是橫向的 X 軸,交叉軸(Cross Axis)就是豎向的 Y 軸,如下圖所示。

主軸是橫向的X軸,交叉軸是豎向的Y軸

如果你選擇了 column 或者 column-reverse,那麼主軸(Main Axis)就變成是豎向的 Y 軸,交叉軸(Cross Axis)就是橫向的 X 軸,如下圖所示。

主軸是豎向的Y軸,交叉軸是橫向的X軸

起始線和終止線

過去,CSS 的書寫模式主要被認爲是水平的,從左到右的。但現代的佈局方式涵蓋了書寫模式的範圍,所以我們不再假設一行文字是從文檔的左上角開始向右書寫的。

對於不同的語言來說,其書寫方向不同,例如英文是從左到右,但阿拉伯文則是從右到左。那麼對於這兩種語言來說,其xx會有所不同 TODO。舉個簡單的例子,如果 flex-direction 是 row ,並且我是在書寫英文。由於英文是從左到右書寫的,那麼主軸的起始線是左邊,終止線是右邊,如下圖所示。

-w557

但如果我在書寫阿拉伯文,由於阿拉伯文是從右到左的,那麼主軸的起始線是右邊,終止線是左邊,如下圖所示。

-w541

在 Flex 佈局中,起始線和終止線決定了 Flex 容器中的 Flex 元素從哪個方向開始排列。 舉個簡單例子,如果我們通過 direction: ltr 設置了文字書寫方向是從左到右,那麼起始線就是左邊,終止線就是右邊。此時,如果我們設置的 flex-direction 值是 row,那麼 Flex 元素將會從左到右開始排列。但如果我們設置的 flex-direction 值是 row-reverse,那麼 Flex 元素將會從右到左開始排列。

在上面的例子中,交叉軸的起始線是 flex 容器的頂部,終止線是底部,因爲兩種語言都是水平書寫模式。但如果有一種語言,它的書寫形式是從底部到頂部,那麼當設置 flex-direction 爲 column 或 column-reverse 時,也會有類似的變化。

Flex 容器與 Flex 元素

我們把一個容器的 display 屬性值改爲 flex 或者 inline-flex 之後,該容器就變成了 Flex 容器,而容器中的直系子元素就會變爲 flex 元素。如下代碼所示,parent 元素就是 Flex 容器,son 元素就是 Flex 元素。

<style>
#parent {
    display: flex;
}
</style>
<div id="parent">
    <div id="son"></div>
</div>

Flex 核心屬性

對於 Flex 來說,它有非常多的用法,但核心屬性卻相對較少。這裏我只簡單介紹幾個核心屬性,如果你想了解更多 Flex 的屬性,可以去 Mozilla 官網查詢,這裏給個傳送門:flex 佈局的基本概念 - CSS:層疊樣式表 | MDN

對於 Flex 佈局來說,其核心屬性有如下幾個:

  1. flex-direction 主軸方向
  2. flex 伸縮係數及初始值
  3. justify-content 主軸方向對齊
  4. align-items 交叉軸方向對齊

flex-direction 主軸方向

如上文所介紹過的,flex-direction 定義了主軸的方向,可以取 4 個值,分別是:

  • row 默認值
  • row-reverse
  • column
  • column-reverse

一旦主軸確定了,交叉軸也確定了。主軸和交叉軸與後續的對齊屬性有關,因此弄懂它們非常重要!舉個很簡單的例子,如下的代碼將展示下圖的展示效果。

.box {
  display: flex;
  flex-direction: row-reverse;
}

<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

-w538

如果你將 flex-direction 改成 column-reverse,那麼將會變成如下的效果,如下圖所示。

-w541

flex 伸縮係數及初始值

前面說到 Flex 佈局可以很方便地進行響應式佈局,其實就是通過 flex 屬性來實現的。flex 屬性其實是 flex-grow、flex-shrink、flex-basis 這三個參數的縮寫形式,如下代碼所示。

flex-grow: 1;
flex-shrink: 1;
flex-basis: 200px;
/* 上面的設置等價於下面 flex 屬性的設置 */
flex: 1 1 200px;

在考慮這幾個屬性的作用之前,需要先了解一下 可用空間 available space 這個概念。這幾個 flex 屬性的作用其實就是改變了 flex 容器中的可用空間的行爲。

假設在 1 個 500px 的容器中,我們有 3 個 100px 寬的元素,那麼這 3 個元素需要佔 300px 的寬,剩下 200px 的可用空間。在默認情況下,flexbox 的行爲會把這 200px 的空間留在最後一個元素的後面。

-w537

如果期望這些元素能自動地擴展去填充滿剩下的空間,那麼我們需要去控制可用空間在這幾個元素間如何分配,這就是元素上的那些 flex 屬性要做的事。

flex-basis

flex-basis 屬性用於設置 Flex 元素的大小,其默認值是 auto。此時瀏覽器會檢查元素是否有確定的尺寸,如果有確定的尺寸則用該尺寸作爲 Flex 元素的尺寸,否則就採用元素內容的尺寸。

flex-grow

flex-grow 若被賦值爲一個正整數,flex 元素會以 flex-basis 爲基礎,沿主軸方向增長尺寸。這會使該元素延展,並佔據此方向軸上的可用空間(available space)。如果有其他元素也被允許延展,那麼他們會各自佔據可用空間的一部分。

舉個例子,上面的例子中有 a、b、c 個 Flex 元素。如果我們給上例中的所有元素設定 flex-grow 值爲 1,容器中的可用空間會被這些元素平分。它們會延展以填滿容器主軸方向上的空間。

但很多時候,我們可能都需要按照比例來劃分剩餘的空間。此時如果第一個元素 flex-grow 值爲 2,其他元素值爲 1,則第一個元素將佔有 2/4(上例中,即爲 200px 中的 100px), 另外兩個元素各佔有 1/4(各 50px)。

flex-shrink

flex-grow 屬性是處理 flex 元素在主軸上增加空間的問題,相反 flex-shrink 屬性是處理 flex 元素收縮的問題。如果我們的容器中沒有足夠排列 flex 元素的空間,那麼可以把 flex 元素 flex-shrink 屬性設置爲正整數,以此來縮小它所佔空間到 flex-basis 以下。

與flex-grow屬性一樣,可以賦予不同的值來控制 flex 元素收縮的程度 —— 給flex-shrink屬性賦予更大的數值可以比賦予小數值的同級元素收縮程度更大。

justify-content 主軸方向對齊

justify-content 屬性用來使元素在主軸方向上對齊,它的初始值是 flex-start,即元素從容器的起始線排列。justify-content 屬性有如下 5 個不同的值:

  • flex-start:從起始線開始排列,默認值。
  • flex-end::從終止線開始排列。
  • center:在中間排列。
  • space-around:每個元素左右空間相等。
  • space-between:把元素排列好之後,剩餘的空間平均分配到元素之間。

各個不同的對齊方式的效果如下圖所示。

flex-start:

-w454

flex-end:

-w444

center:

-w449

space-around:

-w442

space-between:

-w453

align-items 交叉軸方向對齊

align-items 屬性可以使元素在交叉軸方向對齊,它的初始值是 stretch,即拉伸到最高元素的高度。align-items 屬性有如下 5 個不同的值:

  • stretch:拉伸到最高元素的高度,默認值。
  • flex-start:按 flex 容器起始位置對齊。
  • flex-end:按 flex 容器結束爲止對齊。
  • center:居中對齊。
  • baseline:始終按文字基線對齊。

各個不同的對齊方式的效果如下圖所示。

stretch:

-w448

flex-start:

-w439

flex-end:

-w438

center:

-w444

要注意的事,無論 align-items 還是 justify-content,它們都是以主軸或者交叉軸爲參考的,而不是橫向和豎向爲參考的,明白這點很重要。

Flex 默認屬性

由於所有 CSS 屬性都會有一個初始值,所以當沒有設置任何默認值時,flex 容器中的所有 flex 元素都會有下列行爲:

  • 元素排列爲一行 (flex-direction 屬性的初始值是 row)。
  • 元素從主軸的起始線開始。
  • 元素不會在主維度方向拉伸,但是可以縮小。
  • 元素被拉伸來填充交叉軸大小。
  • flex-basis 屬性爲 auto。
  • flex-wrap 屬性爲 nowrap。

弄清楚 Flex 元素的默認值有利於我們更好地進行佈局排版。

實戰項目拆解

看了那麼多的 Flex 佈局知識點,總感覺乾巴巴的,是時候來看看別人在項目中是怎麼用的了。

-w1290

上面是我在 CodePen 找到的一個案例,這樣的一個佈局就是用 Flex 佈局來實現的。通過簡單的分析,其實我們可以拆解出其 Flex 佈局方法,大致如下圖所示。

-w1297

首先整體分爲兩大部分,即導航欄和內容區域,這部分的主軸縱向排列的(flex-direction: column),如上圖紅框部分。隨後在內容區域,又將其分成了左邊的導航欄和右邊的內容區域,此時這塊內容是橫向排列的(flex-direction: row),如下上圖藍框部分。

剩下的內容佈局也大致類似,其實就是無限套娃下去。由於偏於原因,這裏就不繼續深入拆解了,大致的佈局思路已經說得很清楚了。

有了 Flex 佈局之後,貌似佈局也變得非常簡單了。但紙上得來終覺淺,還是得自己實際動手練練才知道容易不容易,不然就變成紙上談兵了!

總結

看到這裏,關於 Flex 佈局的核心點就介紹得差不多了。掌握好這幾個核心的知識點,開始去實踐練習基本上沒有什麼太大的問題了。剩下的一些比較小衆的屬性,等用到的時候再去查查看就足夠了。

接下來更多的時間,就是找多幾個實戰案例實踐,唯有實踐才能鞏固所學知識點。後面有機會,我將分享我在 Flex 佈局方面的項目實踐。

如果這篇文章對你有幫助,記得一鍵三連支持我!

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章