跳轉到內容

CSS Flexbox 彈性佈局從零到精通 2026 | 零基礎入門教程

CSS Flexbox 彈性佈局從零到精通

你是否曾被網頁佈局搞得焦頭爛額?用 float 排版總是錯位,用 position 定位又總是對不齊?別擔心,Flexbox(彈性佈局)就是來拯救你的!這篇教程會從零開始,用大白話帶你徹底搞懂 Flexbox。


一、什麼是 Flexbox?

1.1 通俗理解

想象你有一個紙箱子(容器),裡面放著幾本書(子元素):

  • 不用 Flexbox:書隨便亂放,你很難控制它們的位置
  • 用 Flexbox:你可以讓書整齊排列、自動等間距、自動居中、自動撐滿空間

一句話總結:Flexbox 就是讓容器裡的子元素「聽話地排列」的一種佈局方式。

1.2 什麼時候用 Flexbox?

場景例子
水平居中一個按鈕在導航欄中間
垂直居中文字在卡片正中間
等間距排列導航菜單的幾個鏈接等距排開
自適應寬度側邊欄固定寬度,內容區自動撐滿
按鈕組幾個按鈕緊挨著排成一行

1.3 最簡單的例子

先來個最簡單的例子,感受一下 Flexbox 的魔力:

html
<!-- HTML -->
<div class="box">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
css
/* CSS */
.box {
  display: flex;  /* 加上這一行,魔法就發生了! */
}

.item {
  width: 80px;
  height: 80px;
  background: #4a90d9;
  color: white;
  font-size: 24px;
  text-align: center;
  line-height: 80px;  /* 讓數字垂直居中 */
}

發生了什麼? 三個方塊自動排成了一行,而且中間沒有多餘的空隙。這就是 Flexbox 最基本的效果。

💡 關鍵點display: flex 寫在父元素上,它會讓所有直接子元素變成彈性佈局。


二、兩個核心概念:主軸和交叉軸

這是學習 Flexbox 最重要的概念,搞懂了這個,後面的屬性都是順理成章的。

2.1 什麼是主軸和交叉軸?

想象你在紙上畫了一條橫線,一條豎線:

        交叉軸(Cross Axis)

            |
            |
  ──────────┼──────────→  主軸(Main Axis)
            |
            |
  • 主軸:子元素排列的方向(默認是水平方向,從左到右)
  • 交叉軸:與主軸垂直的方向(默認是豎直方向,從上到下)

💡 大白話:主軸就是子元素「排隊的方向」,交叉軸就是「垂直於排隊的方向」。

2.2 改變主軸方向

flex-direction 可以改變主軸方向:

css
.box {
  display: flex;

  /* 1. 從左到右排列(默認值) */
  flex-direction: row;

  /* 2. 從右到左排列 */
  flex-direction: row-reverse;

  /* 3. 從上到下排列(主軸變成豎直方向) */
  flex-direction: column;

  /* 4. 從下到上排列 */
  flex-direction: column-reverse;
}

用圖來表示就是:

row(默認)          column
┌──────────────┐    ┌──────┐
│ [1] [2] [3]  │    │ [1]  │
└──────────────┘    │ [2]  │
                    │ [3]  │
                    └──────┘

💡 記憶技巧

  • row = 行 = 水平排列
  • column = 列 = 垂直排列
  • 加上 -reverse 就是反過來

三、容器屬性(寫在父元素上的屬性)

接下來學習的屬性都寫在父元素(設置了 display: flex 的元素)上。

3.1 justify-content(主軸對齊)

這個屬性控制子元素在主軸上怎麼對齊。這是最常用的屬性之一!

css
.box {
  display: flex;

  /* 1. 靠左排列(默認值) */
  justify-content: flex-start;

  /* 2. 靠右排列 */
  justify-content: flex-end;

  /* 3. 居中排列 */
  justify-content: center;

  /* 4. 兩端對齊,中間等分 */
  justify-content: space-between;

  /* 5. 完全等分(每個元素左右間距一樣) */
  justify-content: space-evenly;

  /* 6. 間距相同,首尾間距是中間的一半 */
  justify-content: space-around;
}

用圖來表示(假設容器寬度比子元素總寬度大):

flex-start        center           space-between
┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│[1][2][3]     │  │  [1][2][3]   │  │[1]  [2]  [3] │
└──────────────┘  └──────────────┘  └──────────────┘

space-evenly      space-around
┌──────────────┐  ┌──────────────┐
│ [1] [2] [3]  │  │[1]  [2]  [3] │
└──────────────┘  └──────────────┘

💡 最常用的是哪幾個?

  • center:水平居中
  • space-between:導航欄菜單兩端對齊
  • space-evenly:均勻分佈

3.2 align-items(交叉軸對齊)

這個屬性控制子元素在交叉軸(垂直方向)上怎麼對齊。

css
.box {
  display: flex;
  height: 200px;  /* 容器要有高度才能看到效果 */

  /* 1. 靠上對齊 */
  align-items: flex-start;

  /* 2. 靠下對齊 */
  align-items: flex-end;

  /* 3. 垂直居中 */
  align-items: center;

  /* 4. 拉伸填滿(默認值) */
  align-items: stretch;

  /* 5. 文字基線對齊 */
  align-items: baseline;
}

用圖來表示:

flex-start       center           flex-end
┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│[1] [2] [3]   │  │              │  │              │
│              │  │[1] [2] [3]   │  │              │
│              │  │              │  │[1] [2] [3]   │
└──────────────┘  └──────────────┘  └──────────────┘

💡 最常用的場景align-items: center 讓子元素垂直居中!

3.3 完美居中(最經典用法)

水平居中 + 垂直居中 = 完美居中,只要兩行代碼:

css
.box {
  display: flex;
  justify-content: center;  /* 水平居中 */
  align-items: center;      /* 垂直居中 */
  height: 200px;            /* 容器要有高度 */
}
┌──────────────┐
│              │
│              │
│    [盒子]    │  ← 水平和垂直都居中了!
│              │
│              │
└──────────────┘

💡 以前沒有 Flexbox 的時候,垂直居中是 CSS 最頭疼的問題之一,各種 hack 層出不窮。現在有了 Flexbox,兩行代碼搞定!

3.4 flex-wrap(是否換行)

默認情況下,Flexbox 的子元素會擠在一行裡,不會換行:

css
.box {
  display: flex;

  /* 1. 不換行,擠在一起(默認值) */
  flex-wrap: nowrap;

  /* 2. 放不下就換行 */
  flex-wrap: wrap;

  /* 3. 換行,但順序反過來 */
  flex-wrap: wrap-reverse;
}
nowrap(默認)       wrap
┌──────────────┐    ┌──────────────┐
│[1][2][3][4]5]│    │[1] [2] [3]   │
└──────────────┘    │[4] [5]       │
  ↑ 第5個被擠扁了    └──────────────┘

💡 實際開發建議:大多數情況下設置為 flex-wrap: wrap,防止子元素被擠壓變形。

3.5 flex-flow(簡寫)

flex-flowflex-directionflex-wrap 的簡寫:

css
/* 等價於 flex-direction: row; flex-wrap: wrap; */
.box {
  display: flex;
  flex-flow: row wrap;
}

/* 等價於 flex-direction: column; flex-wrap: nowrap; */
.box {
  display: flex;
  flex-flow: column nowrap;
}

3.6 align-content(多行對齊)

當子元素換行後有多行時,align-content 控制行與行之間的間距:

css
.box {
  display: flex;
  flex-wrap: wrap;  /* 必須允許換行 */
  height: 300px;    /* 容器要有足夠高度 */

  /* 多行之間兩端對齊 */
  align-content: space-between;

  /* 多行整體居中 */
  align-content: center;

  /* 多行之間均勻分佈 */
  align-content: space-evenly;
}

💡 注意align-content 只在換行flex-wrap: wrap)且有多行時才有效。如果只有一行,這個屬性不起作用。

3.7 gap(間距)

這是一個非常實用的新屬性,可以直接設置子元素之間的間距:

css
.box {
  display: flex;
  gap: 16px;              /* 所有方向間距 16px */
  /* 或者分別設置 */
  row-gap: 16px;          /* 行間距 */
  column-gap: 24px;       /* 列間距 */
}

💡 以前我們常用 margin 來設置間距,但 margin 會有「最後一個元素也有外邊距」的問題。用 gap 就完美解決了!


四、子元素屬性(寫在子元素上的屬性)

接下來學習的屬性寫在子元素上。

4.1 flex-grow(放大比例)

控制子元素在有剩餘空間時,如何分配多餘的空間。

css
.item1 {
  /* 默認值 0,不放大 */
  flex-grow: 0;
}

.item2 {
  /* 佔據所有剩餘空間 */
  flex-grow: 1;
}

.item3 {
  /* 和 item2 平分剩餘空間 */
  flex-grow: 1;
}

通俗理解:假設容器有 100px 剩餘空間,如果兩個子元素分別設置 flex-grow: 1flex-grow: 3,那麼它們會按照 1:3 的比例分配剩餘空間(一個拿 25px,另一個拿 75px)。

沒有 flex-grow          item2: flex-grow: 1
┌──────────────────┐    ┌──────────────────┐
│[1] [2] [3]       │    │[1] [2         3] │
└──────────────────┘    └──────────────────┘
  ↑ 右邊有空餘空間        ↑ item2 自動撐滿了剩餘空間

💡 常見用法:側邊欄固定寬度 + 內容區 flex-grow: 1 自動撐滿

4.2 flex-shrink(縮小比例)

控制子元素在空間不夠時,如何縮小。默認值是 1(會等比縮小)。

css
.sidebar {
  /* 設置為 0,表示不縮小 */
  flex-shrink: 0;
  width: 200px;  /* 側邊欄固定 200px */
}

.content {
  /* 默認值 1,會自動縮小 */
  flex-shrink: 1;
  flex-grow: 1;  /* 同時允許放大 */
}

💡 常見用法:側邊欄 flex-shrink: 0 防止被擠壓

4.3 flex-basis(基礎尺寸)

設置子元素在主軸上的初始大小,優先級高於 width(或 height)。

css
.item {
  /* 像 width 一樣用 */
  flex-basis: 200px;

  /* 根據內容自動撐開 */
  flex-basis: auto;  /* 默認值 */

  /* 根據內容計算 */
  flex-basis: content;

  /* 也可以用百分比 */
  flex-basis: 50%;
}

💡 大白話flex-basis 就是「在放大或縮小之前,子元素應該有多大」。

4.4 flex(簡寫,最常用!)

flexflex-growflex-shrinkflex-basis 的簡寫,實際開發中最常用

css
/* 最常用的寫法 */
.item {
  flex: 1;  /* 等價於 flex: 1 1 0% */
}

/* 固定不放大不縮小 */
.sidebar {
  flex: 0 0 200px;  /* 等價於 flex-grow:0; flex-shrink:0; flex-basis:200px */
}

/* 只放大不縮小 */
.content {
  flex: 1 0 auto;
}

常用的 flex 值速查表:

寫法含義適用場景
flex: 0 1 auto默認值,不放大但可縮小普通元素
flex: 1放大填滿剩餘空間內容區
flex: 0 0 200px固定 200px 不變側邊欄
flex: none不放大不縮小固定尺寸元素

💡 實際開發建議:直接用 flex: 1flex: 0 0 xxxpx 就夠了,不用單獨寫三個屬性。

4.5 order(排序)

order 可以改變子元素的顯示順序,不需要改 HTML

css
.item1 { order: 3; }  /* 排第3 */
.item2 { order: 1; }  /* 排第1 */
.item3 { order: 2; }  /* 排第2 */

/* 顯示順序:item2 → item3 → item1 */

💡 默認值是 0,值越小越靠前。可以用負數讓它排到最前面。

4.6 align-self(單獨對齊)

align-self 可以讓某個子元素單獨設置交叉軸對齊方式,覆蓋父元素的 align-items

css
.box {
  display: flex;
  align-items: center;  /* 所有子元素垂直居中 */
}

.special-item {
  align-self: flex-start;  /* 但這個特殊元素靠上對齊 */
}

五、實戰練習

5.1 練習一:導航欄

最經典的 Flexbox 應用——導航欄佈局:

html
<nav class="navbar">
  <div class="logo">我的網站</div>
  <div class="menu">
    <a href="#">首頁</a>
    <a href="#">產品</a>
    <a href="#">關於</a>
    <a href="#">聯繫</a>
  </div>
  <button class="login">登錄</button>
</nav>
css
.navbar {
  display: flex;
  align-items: center;       /* 垂直居中 */
  justify-content: space-between;  /* 兩端對齊 */
  padding: 0 20px;
  height: 60px;
  background: #1a1a2e;
  color: white;
}

.logo {
  font-size: 20px;
  font-weight: bold;
}

.menu {
  display: flex;
  gap: 20px;  /* 菜單項之間的間距 */
}

.menu a {
  color: white;
  text-decoration: none;
}

.login {
  padding: 8px 20px;
  background: #4a90d9;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

效果: Logo 在左邊,菜單在中間,登錄按鈕在右邊,全部垂直居中。

5.2 練習二:卡片居中

讓一個卡片在頁面正中間顯示:

html
<div class="page">
  <div class="card">
    <h2>歡迎登錄</h2>
    <input type="text" placeholder="用戶名">
    <input type="password" placeholder="密碼">
    <button>登錄</button>
  </div>
</div>
css
.page {
  display: flex;
  justify-content: center;  /* 水平居中 */
  align-items: center;      /* 垂直居中 */
  min-height: 100vh;        /* 至少佔滿整個屏幕高度 */
  background: #f0f2f5;
}

.card {
  background: white;
  padding: 40px;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  width: 360px;
  display: flex;
  flex-direction: column;  /* 子元素豎向排列 */
  gap: 16px;               /* 子元素間距 16px */
}

.card input {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 6px;
  font-size: 14px;
}

.card button {
  padding: 10px;
  background: #4a90d9;
  color: white;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  cursor: pointer;
}

5.3 練習三:側邊欄 + 內容區

經典的後臺管理佈局:

html
<div class="layout">
  <aside class="sidebar">
    <div class="menu-item">儀表盤</div>
    <div class="menu-item">用戶管理</div>
    <div class="menu-item">系統設置</div>
  </aside>
  <main class="content">
    <h1>歡迎回來</h1>
    <p>這裡是內容區域,會自動撐滿剩餘空間。</p>
  </main>
</div>
css
.layout {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  flex: 0 0 240px;      /* 固定 240px,不放大不縮小 */
  background: #1a1a2e;
  color: white;
  padding: 20px 0;
}

.menu-item {
  padding: 12px 24px;
  cursor: pointer;
}

.menu-item:hover {
  background: rgba(255, 255, 255, 0.1);
}

.content {
  flex: 1;              /* 自動撐滿剩餘空間 */
  padding: 24px;
  background: #f5f5f5;
}

5.4 練習四:按鈕組

幾個按鈕緊挨著排成一行:

html
<div class="button-group">
  <button>取消</button>
  <button>上一步</button>
  <button class="primary">下一步</button>
</div>
css
.button-group {
  display: flex;
  gap: 8px;  /* 按鈕之間 8px 間距 */
}

.button-group button {
  padding: 8px 16px;
  border: 1px solid #ddd;
  border-radius: 6px;
  background: white;
  cursor: pointer;
}

.button-group .primary {
  background: #4a90d9;
  color: white;
  border-color: #4a90d9;
}

5.5 練習五:響應式卡片列表

卡片自動換行,每行顯示固定數量:

html
<div class="card-list">
  <div class="card">卡片1</div>
  <div class="card">卡片2</div>
  <div class="card">卡片3</div>
  <div class="card">卡片4</div>
  <div class="card">卡片5</div>
  <div class="card">卡片6</div>
</div>
css
.card-list {
  display: flex;
  flex-wrap: wrap;        /* 允許換行 */
  gap: 16px;              /* 卡片間距 */
}

.card {
  /* 每行3個卡片,減去間距 */
  width: calc((100% - 32px) / 3);
  height: 150px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}

/* 響應式:小屏幕每行2個 */
@media (max-width: 768px) {
  .card {
    width: calc((100% - 16px) / 2);
  }
}

/* 手機屏幕每行1個 */
@media (max-width: 480px) {
  .card {
    width: 100%;
  }
}

六、常見問題

6.1 為什麼我的 flex: 1 不生效?

css
/* 問題:父元素沒有設置 display: flex */
.parent {
  /* 忘了加這一行! */
  /* display: flex; */
}

.child {
  flex: 1;  /* 不生效,因為父元素不是 flex 容器 */
}

解決: 確保父元素設置了 display: flex

6.2 為什麼 align-items: center 不生效?

css
/* 問題:父元素沒有高度 */
.box {
  display: flex;
  align-items: center;
  /* 沒有設置 height,父元素高度等於子元素高度,看不出居中效果 */
}

/* 解決:給父元素設置高度 */
.box {
  display: flex;
  align-items: center;
  height: 200px;  /* 現在能看出來了 */
}

6.3 flex-basis 和 width 有什麼區別?

css
/* flex-basis 優先級更高 */
.item {
  flex-basis: 200px;
  width: 100px;  /* 會被忽略,實際寬度是 200px */
}

/* 如果主軸是豎直方向(flex-direction: column),
   flex-basis 控制的是高度,width 控制的是寬度 */
.column-box {
  display: flex;
  flex-direction: column;
}

.column-box .item {
  flex-basis: 100px;  /* 這是高度 */
  width: 200px;       /* 這是寬度 */
}

6.4 子元素被擠扁了怎麼辦?

css
/* 問題:子元素內容太多被擠壓變形 */
.box {
  display: flex;
  /* 默認 flex-shrink: 1,會縮小 */
}

/* 解決:禁止縮小 */
.box .item {
  flex-shrink: 0;  /* 不再縮小 */
  /* 或者 */
  flex: 0 0 auto;  /* 不放大、不縮小、按內容大小 */
}

七、Flexbox 速查表

7.1 父元素屬性

屬性作用常用值
display開啟彈性佈局flex
flex-direction排列方向row / column
justify-content主軸對齊center / space-between
align-items交叉軸對齊center / flex-start
flex-wrap是否換行wrap
gap子元素間距16px
align-content多行間距space-between

7.2 子元素屬性

屬性作用常用值
flex放大/縮小/基礎尺寸1 / 0 0 200px
order排序數字(默認 0)
align-self單獨對齊center / flex-start

7.3 最常用組合

場景CSS
水平垂直居中display:flex; justify-content:center; align-items:center;
兩端對齊display:flex; justify-content:space-between;
側邊欄+內容側邊欄 flex:0 0 240px;,內容區 flex:1;
垂直排列display:flex; flex-direction:column;
卡片換行display:flex; flex-wrap:wrap; gap:16px;

八、總結

讓我們回顧一下這篇教程的要點:

  1. display: flex 寫在父元素上,開啟彈性佈局
  2. 主軸是子元素排列方向,交叉軸是垂直方向
  3. justify-content 控制主軸對齊(水平方向)
  4. align-items 控制交叉軸對齊(垂直方向)
  5. flex: 1 讓子元素撐滿剩餘空間
  6. flex-wrap: wrap 讓子元素放不下時自動換行
  7. gap 設置子元素間距,比 margin 更好用
  8. 完美居中只需要 justify-content: center + align-items: center

記住這些,日常開發中 90% 的佈局問題都能解決了!


相關閱讀:

最後更新於: