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

你是否曾被網頁佈局搞得焦頭爛額?用 float 排版總是錯位,用 position 定位又總是對不齊?別擔心,Flexbox(彈性佈局)就是來拯救你的!這篇教程會從零開始,用大白話帶你徹底搞懂 Flexbox。
一、什麼是 Flexbox?
1.1 通俗理解
想象你有一個紙箱子(容器),裡面放著幾本書(子元素):
- 不用 Flexbox:書隨便亂放,你很難控制它們的位置
- 用 Flexbox:你可以讓書整齊排列、自動等間距、自動居中、自動撐滿空間
一句話總結:Flexbox 就是讓容器裡的子元素「聽話地排列」的一種佈局方式。
1.2 什麼時候用 Flexbox?
| 場景 | 例子 |
|---|---|
| 水平居中 | 一個按鈕在導航欄中間 |
| 垂直居中 | 文字在卡片正中間 |
| 等間距排列 | 導航菜單的幾個鏈接等距排開 |
| 自適應寬度 | 側邊欄固定寬度,內容區自動撐滿 |
| 按鈕組 | 幾個按鈕緊挨著排成一行 |
1.3 最簡單的例子
先來個最簡單的例子,感受一下 Flexbox 的魔力:
<!-- HTML -->
<div class="box">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>/* 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 可以改變主軸方向:
.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(主軸對齊)
這個屬性控制子元素在主軸上怎麼對齊。這是最常用的屬性之一!
.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(交叉軸對齊)
這個屬性控制子元素在交叉軸(垂直方向)上怎麼對齊。
.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 完美居中(最經典用法)
水平居中 + 垂直居中 = 完美居中,只要兩行代碼:
.box {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
height: 200px; /* 容器要有高度 */
}┌──────────────┐
│ │
│ │
│ [盒子] │ ← 水平和垂直都居中了!
│ │
│ │
└──────────────┘💡 以前沒有 Flexbox 的時候,垂直居中是 CSS 最頭疼的問題之一,各種 hack 層出不窮。現在有了 Flexbox,兩行代碼搞定!
3.4 flex-wrap(是否換行)
默認情況下,Flexbox 的子元素會擠在一行裡,不會換行:
.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-flow 是 flex-direction 和 flex-wrap 的簡寫:
/* 等價於 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 控制行與行之間的間距:
.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(間距)
這是一個非常實用的新屬性,可以直接設置子元素之間的間距:
.box {
display: flex;
gap: 16px; /* 所有方向間距 16px */
/* 或者分別設置 */
row-gap: 16px; /* 行間距 */
column-gap: 24px; /* 列間距 */
}💡 以前我們常用 margin 來設置間距,但 margin 會有「最後一個元素也有外邊距」的問題。用
gap就完美解決了!
四、子元素屬性(寫在子元素上的屬性)
接下來學習的屬性寫在子元素上。
4.1 flex-grow(放大比例)
控制子元素在有剩餘空間時,如何分配多餘的空間。
.item1 {
/* 默認值 0,不放大 */
flex-grow: 0;
}
.item2 {
/* 佔據所有剩餘空間 */
flex-grow: 1;
}
.item3 {
/* 和 item2 平分剩餘空間 */
flex-grow: 1;
}通俗理解:假設容器有 100px 剩餘空間,如果兩個子元素分別設置 flex-grow: 1 和 flex-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(會等比縮小)。
.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)。
.item {
/* 像 width 一樣用 */
flex-basis: 200px;
/* 根據內容自動撐開 */
flex-basis: auto; /* 默認值 */
/* 根據內容計算 */
flex-basis: content;
/* 也可以用百分比 */
flex-basis: 50%;
}💡 大白話:
flex-basis就是「在放大或縮小之前,子元素應該有多大」。
4.4 flex(簡寫,最常用!)
flex 是 flex-grow、flex-shrink、flex-basis 的簡寫,實際開發中最常用:
/* 最常用的寫法 */
.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: 1或flex: 0 0 xxxpx就夠了,不用單獨寫三個屬性。
4.5 order(排序)
用 order 可以改變子元素的顯示順序,不需要改 HTML:
.item1 { order: 3; } /* 排第3 */
.item2 { order: 1; } /* 排第1 */
.item3 { order: 2; } /* 排第2 */
/* 顯示順序:item2 → item3 → item1 */💡 默認值是 0,值越小越靠前。可以用負數讓它排到最前面。
4.6 align-self(單獨對齊)
align-self 可以讓某個子元素單獨設置交叉軸對齊方式,覆蓋父元素的 align-items:
.box {
display: flex;
align-items: center; /* 所有子元素垂直居中 */
}
.special-item {
align-self: flex-start; /* 但這個特殊元素靠上對齊 */
}五、實戰練習
5.1 練習一:導航欄
最經典的 Flexbox 應用——導航欄佈局:
<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>.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 練習二:卡片居中
讓一個卡片在頁面正中間顯示:
<div class="page">
<div class="card">
<h2>歡迎登錄</h2>
<input type="text" placeholder="用戶名">
<input type="password" placeholder="密碼">
<button>登錄</button>
</div>
</div>.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 練習三:側邊欄 + 內容區
經典的後臺管理佈局:
<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>.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 練習四:按鈕組
幾個按鈕緊挨著排成一行:
<div class="button-group">
<button>取消</button>
<button>上一步</button>
<button class="primary">下一步</button>
</div>.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 練習五:響應式卡片列表
卡片自動換行,每行顯示固定數量:
<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>.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 不生效?
/* 問題:父元素沒有設置 display: flex */
.parent {
/* 忘了加這一行! */
/* display: flex; */
}
.child {
flex: 1; /* 不生效,因為父元素不是 flex 容器 */
}解決: 確保父元素設置了 display: flex。
6.2 為什麼 align-items: center 不生效?
/* 問題:父元素沒有高度 */
.box {
display: flex;
align-items: center;
/* 沒有設置 height,父元素高度等於子元素高度,看不出居中效果 */
}
/* 解決:給父元素設置高度 */
.box {
display: flex;
align-items: center;
height: 200px; /* 現在能看出來了 */
}6.3 flex-basis 和 width 有什麼區別?
/* 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 子元素被擠扁了怎麼辦?
/* 問題:子元素內容太多被擠壓變形 */
.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; |
八、總結
讓我們回顧一下這篇教程的要點:
display: flex寫在父元素上,開啟彈性佈局- 主軸是子元素排列方向,交叉軸是垂直方向
justify-content控制主軸對齊(水平方向)align-items控制交叉軸對齊(垂直方向)flex: 1讓子元素撐滿剩餘空間flex-wrap: wrap讓子元素放不下時自動換行gap設置子元素間距,比 margin 更好用- 完美居中只需要
justify-content: center+align-items: center
記住這些,日常開發中 90% 的佈局問題都能解決了!
相關閱讀: