cover

結論先講

Flexbox 處理一維佈局(單一軸向排列)。一維的定義:你只在一個方向上分配空間

✅ 適合 Flexbox:

  • 導覽列(一排項目橫向排)
  • 卡片列(單排卡片)
  • 水平/垂直置中
  • 表單行(label + input)
  • 分散對齊(左右兩邊的元素)

❌ 不適合 Flexbox(該用 Grid):

  • 二維表格(列 + 行同時對齊)
  • 雜誌式版面
  • Dashboard 網格

搞清楚這條界線就不會硬 flex 所有東西。


心智模型:容器 + 項目

Flexbox 有兩個角色:

<div class="container">   <!-- display: flex -->
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
  • Flex 容器display: flex 的元素
  • Flex 項目:容器的直接子元素

不是所有屬性都放在容器,也不是所有屬性都放在項目:

放容器放項目
flex-directionflex-grow
flex-wrapflex-shrink
justify-contentflex-basis
align-itemsalign-self
gaporder

兩條軸:主軸 & 交叉軸

Flexbox 有兩條軸,決定所有對齊屬性的方向:

flex-direction: row(預設)
┌──────────────────────────────┐
│ →  → 主軸(main axis)→  →  │
│                               │
│ ↓ 交叉軸(cross axis)↓       │
└──────────────────────────────┘

flex-direction: column
┌──────────────────────────────┐
│ ↓ 主軸                        │
│ ↓                             │
│ → 交叉軸                       │
└──────────────────────────────┘

重要:主軸跟交叉軸會互換。justify-content 永遠沿主軸align-items 永遠沿交叉軸


justify-content(主軸分配)

.container { display: flex; justify-content: <value>; }
效果
flex-start(預設)從起點緊靠排
flex-end從終點緊靠排
center置中
space-between兩端對齊,中間平均
space-around每項左右等距
space-evenly所有間距相等(含邊)

視覺對照

[A] [B] [C]              flex-start
            [A] [B] [C]  flex-end
     [A] [B] [C]         center
[A]      [B]      [C]   space-between
  [A]    [B]    [C]     space-around
    [A]  [B]  [C]       space-evenly

align-items(交叉軸對齊)

.container { display: flex; align-items: <value>; }
效果
stretch(預設)拉伸填滿交叉軸
flex-start頂部對齊
flex-end底部對齊
center垂直置中
baseline文字基線對齊

最常用的:垂直水平雙置中

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

CSS 界的「如何置中」折磨了 20 年,Flexbox 兩行解決。


flex 速記屬性(最多人搞不清楚)

每個 item 可以設 flex: X Y Z,三個值:

.item { flex: <grow> <shrink> <basis>; }
  • flex-grow(預設 0):有多餘空間時,這項佔比多少
  • flex-shrink(預設 1):空間不夠時,這項縮多少
  • flex-basis(預設 auto):起始大小

常見組合

.item { flex: 1; }
/* 等同 flex: 1 1 0% — 平均分配可用空間 */
 
.item { flex: 0 0 200px; }
/* 固定 200px,不長不縮 */
 
.item { flex: 1 0 auto; }
/* 按內容起始,有空間就吃,不縮小 */
 
.item { flex: auto; }
/* 等同 flex: 1 1 auto — 跟內容走但可彈性 */

實戰建議:99% 情況你要的是 flex: 1(平均)或 flex: 0 0 Xpx(固定尺寸)。


gap:間距的最佳解法

.container {
  display: flex;
  gap: 16px;  /* 項目之間的間距 */
}

不要用 margin 噴間距:

❌ 壞:

.item { margin-right: 16px; }
.item:last-child { margin-right: 0; }  /* 最後一個要單獨處理 */

✅ 好:

.container { display: flex; gap: 16px; }

gap 自動處理「只在中間出現間距」的邏輯,還相容 flex-wrap


flex-wrap:換行

.container {
  display: flex;
  flex-wrap: wrap;  /* 空間不夠就換行 */
  gap: 16px;
}

配合 flex-basis 做響應式卡片:

.card {
  flex: 1 1 300px;  /* 最小 300px,可長可縮 */
}

空間夠時卡片一排 3 張,縮小時自動變 2 張、1 張。不用 media query。


常見陷阱

陷阱 1:子元素的 width 被忽略

.container { display: flex; }
.item { width: 200px; }

如果容器設 flex-growwidth 可能被壓縮。用 flex: 0 0 200px 替代。

陷阱 2:文字溢出容器

Flex 項目預設 min-width: auto(不是 0)。長文字會把容器撐大:

.item {
  min-width: 0;  /* 關鍵 */
  overflow: hidden;
  text-overflow: ellipsis;
}

陷阱 3:垂直 Flex 容器需要明確高度

.container {
  display: flex;
  flex-direction: column;
  height: 100vh;  /* 沒設高度,align-items 沒意義 */
}

陷阱 4:flex: 1 不一定等高

.container { display: flex; }
.item { flex: 1; }

所有 item 寬度相等(因為 flex-grow: 1但 flex-basis: 0,所以內容不同時高度不一致。要等高設 align-items: stretch(這是預設,但如果被覆寫要明確設)。


什麼時候該切到 Grid

Flexbox 做得很辛苦的情境

┌────────────────────────────────┐
│ Header                          │
├─────┬──────────────────┬───────┤
│ Nav │  Main            │ Aside │
│     │                  │       │
├─────┴──────────────────┴───────┤
│ Footer                          │
└────────────────────────────────┘

這種「列 + 行同時對齊」的版面用 Flexbox 要多層巢狀 + 各種 flex 調整,很快會混亂。

切 Grid。 一個容器就搞定。下一篇講。


實戰 Checklist

  • 只用 Flexbox 做一維排列(單方向)
  • 二維版面(列+行同時對齊)切到 Grid
  • gap 管間距,不要用 margin
  • 垂直置中用 justify-content + align-items
  • 動態寬度元素用 flex: 1,固定尺寸用 flex: 0 0 Xpx
  • 長文字項目加 min-width: 0; overflow: hidden;

工具:DevTools 的 Flexbox Inspector

Chrome/Firefox DevTools 對 flex 容器的元素會顯示 flex badge。點開能視覺化看主軸、交叉軸、間距分配。debug 必備。


相關文章