第 361 篇 · 第 14 卷 前端,沒有極限 2026 年 7 月 6 日 · 台北
ls -lt ./posts --since=2013 REC · node 361 · uplink

css

Flex 空間計算規則

2020 年 03 月 08 日 · 5 分鐘閱讀 · By Wang Casper

此篇是延續先前的 Flex 的文章(圖解:CSS Flex 屬性一點也不難),本篇則是著重在 flex 中的 flex-growflex-shrinkflex-basis 這三個屬性,如果對於 Flex 基礎尚不熟悉的可先閱讀前一篇文章。

首先,回顧下先前的三個屬性介紹:

flex 是縮寫,裡面依序包含三個屬性 flex-growflex-shrinkflex-basis

  • flex-grow: 元件的伸展性,是一個數值,當空間分配還有剩餘時的當前元件的伸展性,預設值為 0,如果設置為 0 則不會縮放。
  • flex-shrink: 元件的收縮性: 元件的伸展性,是一個數值,當空間分配還不足時的當前元件的收縮性,預設值為 0,如果設置為 0 則不會縮放。
  • flex-basis: 元件的基準值,可使用不同的單位值。

在以上的 flex-growflex-shrink 中,這兩個數性可以填入任意整數,關鍵也在於這個任意整數的計算方式如何,本篇將用圖文方式介紹其中運算的規則。

grow, shrink 的計算概念

這兩者所填入的皆是整數,運作的概念上非常接近,都是 按比例分配剩餘空間,只是兩者是在相反的情境下運作,我們先來介紹比較常使用到的 flex-grow,接下來再用相同的概念來理解 shrink

Grow 伸展值,分配剩餘的空間

我們先建立一個簡單的基礎,在一個外部容器上加上 display: flex;,內部則補上 flex: 1; 預期會得到如下的結果:三個等比切分的內元素(三個寬度各佔 33%)。

下方的介面中,可以自行開啟 HTML, CSS 來檢視、調整原始碼,如果看到的結果不符合預期可以點選右下角的 rerun

See the Pen Flex 寬度計算規則 - 1 by Wcc723 (@Wcc723) on CodePen.

接下來,為了讓接下來的實驗更好驗證,對於這些元素再補上一些設定:

  1. 外層容器設定為 600px
  2. 內容最左邊的元素設定 200px 寬度(flex-basis 強制設定)
  3. 右方兩個藍色元素設定 flex-grow: 1

到這個階段會看到以下的結果,三個方框的寬度依然是一致的(都是 200px)。

See the Pen Flex 寬度計算規則 - 2 by Wcc723 (@Wcc723) on CodePen.

接下來,將最右方的元素 flex-grow 改為 2,則可以看到以下的結果。

See the Pen Flex 寬度計算規則 - 3 by Wcc723 (@Wcc723) on CodePen.

由於 Flex 是按比例分配剩餘空間,因此在前面的範例中,兩者 flex-grow 都是 1 的情況下,會呈現 1:1 的結果,這次改為 1:2 那麼寬度的計算上也會改為 1:2,重點如下:

  • 分配空間是依據比例(flex-grow 的總和值再重新分配)
  • 是分配 剩餘的空間,已經佔用的空間不會重新分配

因此,以上方的範例來說:

  1. 總寬度為 600px,最左方的元素佔用 200px 寬度,因此剩餘 400px
  2. flex-grow 分別為 2、1,因此總和為 3
  3. 比例分配上為 400px / 3 = 133.33333px
  4. 左方寬度為 133 * 1,右方元素為 133 * 2 = 266

圖文說明:

依據可分配剩餘空間,依據比例劃分

重新分配大小

接下來,請使用你的開發者工具檢視上方的結果(左方約為 134px,右方為 266px)。

注意,可分配的空間

flex 的可分配空間會隨著條件不同而改變,以下範例來說,中間的元素補上了 100px,我們會發現他的寬度計算會與上一個的範例有所不同。

  • 中間的元素與右邊元素尺寸大小不相上下

See the Pen Flex 寬度計算規則 - 8 by Wcc723 (@Wcc723) on CodePen.

此段的計算邏輯:

  1. 計算出可分配的空間:總寬(600px) - 左方元素(200px) - 中間元素的固定寬(100px) = 300px
  2. 計算比例:300px / 3(flex-grow 總值) = 100px
  3. 重新分配:
  • 右方元素(grow: 2) 100px * 2 = 200px
  • 中間元素(basis: 100px; grow: 1) 100px + 100px * 1 = 200px

接下來,透過開發者工具會得到 接近 上述的結果。

問題:為什麼是接近上述的結果,而不是完全符合呢?

因為 flex 計算上是 分配剩餘的空間,空間上被佔用的因素非常多,如上述的 flex-basis 就是會屬於佔用空間的一種,除此之外包含元素內部的 文字、邊線、任何內容都會影響到佔用空間,因此也會影響到剩餘的空間分配。

Shrink 收縮值,分配多餘的空間

flex-shrinkflex-grow 運作上則是相反,shrink 是將超出的部分重新分配,確保元素不會被裁切(如果足夠被分配完)。

以下範例透過三個 flex-basis: 250px 來超出範圍,並且統一設定 flex-shrinkflex-grow 皆為 0(禁止伸展、收縮),可以得到以下的結果:內元素超出了外容器。

See the Pen Flex 寬度計算規則 - 4 by Wcc723 (@Wcc723) on CodePen.

接下來,將右邊兩個元素 flex-shrink 設為 1,會看到兩個元素多餘的內容收縮到外容器內部並維持相同的寬度,最左方的元素則維持原本的寬度不變。

See the Pen Flex 寬度計算規則 - 5 by Wcc723 (@Wcc723) on CodePen.

接下來,一樣進行 2:1 的 shrink 設置實驗,左方為 flex-shrink: 1,右方為 flex-shrink: 1,接下來你可能會猜想兩者的尺寸應為 2: 1 吧!

See the Pen Flex 寬度計算規則 - 6 by Wcc723 (@Wcc723) on CodePen.

實際結果:當然不是~

上面有提到 shrink 是分配多餘的空間,因此不是全部的空間上都重新分配,所以運作的結果如下:

先計算超出範圍的空間及比例

依據比例重新扣除

接下來,重新使用你的開發者工具,檢視上方的結果吧(會得到中間元素寬度 200px,右方元素寬度 150px)。

遵循軸線

Flex 撇除了原本的寬度、高度的空間定義,改用三個屬性(basis、grow、shrink)來定義一個容器的尺寸,不僅是為了提高容器的空間彈性,除此之外計算出來的空間尺寸還能依據 Flex 的軸線重新計算,大大增加了空間的彈性。

以下範例來說,將 Flex 主軸線切換為 flex-direction: column;,內層元素依然可依據垂直的方式重新分配空間大小,且計算邏輯一致。

See the Pen Flex 寬度計算規則 - 3 - cloumn by Wcc723 (@Wcc723) on CodePen.

如果透過文字還是不容易理解,可以看我過去線上教學的影片 - Flex 寬度計算方法,或是Flex 完整教學