CSS Grid 網格佈局從入門到實戰 2026 | 零基礎入門教程

學會了 Flexbox 之後,你可能會遇到更復雜的佈局需求:比如把頁面分成「頭部、側邊、內容、底部」四個區域,或者做一個相冊網格。這時候 CSS Grid 就登場了!Grid 是比 Flexbox 更強大的二維佈局系統,這篇教程繼續用大白話帶你從零掌握。
一、Grid 和 Flexbox 有什麼區別?
1.1 通俗對比
| 特性 | Flexbox | Grid |
|---|---|---|
| 維度 | 一維(一行或一列) | 二維(行和列同時) |
| 比喻 | 排隊 | 桌子擺盤子 |
| 適用場景 | 導航欄、按鈕組、居中 | 整頁佈局、相冊、表格 |
| 控制方式 | 從內容出發 | 從容器出發 |
大白話理解:
- Flexbox 就像排隊——大家排成一行(或一列),重點是「排隊的方向」
- Grid 就像在桌子上擺盤子——先畫好格子,再把盤子放到指定的格子裡
1.2 什麼時候用 Grid?
| 場景 | 例子 |
|---|---|
| 整頁佈局 | 頭部 + 側邊欄 + 內容 + 底部 |
| 圖片相冊 | 3×3 的照片網格 |
| 表單佈局 | 標籤和輸入框對齊 |
| 卡片網格 | 商品列表、文章列表 |
| 儀表盤 | 多個面板的複雜排列 |
1.3 最簡單的例子
<div class="grid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>.grid {
display: grid;
grid-template-columns: 100px 100px 100px; /* 3列,每列100px */
grid-template-rows: 80px 80px; /* 2行,每行80px */
gap: 10px; /* 間距10px */
}
.item {
background: #4a90d9;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
}效果: 6 個方塊自動排成了 3 列 2 行的網格,整齊又美觀!
┌───────┬───────┬───────┐
│ 1 │ 2 │ 3 │
├───────┼───────┼───────┤
│ 4 │ 5 │ 6 │
└───────┴───────┴───────┘二、定義網格:行和列
2.1 grid-template-columns(定義列)
這是 Grid 中最重要的屬性,用來定義有多少列、每列多寬:
.grid {
display: grid;
/* 3列,每列100px */
grid-template-columns: 100px 100px 100px;
/* 2列,第一列200px,第二列300px */
grid-template-columns: 200px 300px;
/* 3列,每列相等(auto表示均分) */
grid-template-columns: auto auto auto;
}2.2 fr 單位(重點!)
fr 是 Grid 特有的單位,表示「按比例分配剩餘空間」,就像 Flexbox 的 flex-grow:
.grid {
display: grid;
/* 3列等寬 */
grid-template-columns: 1fr 1fr 1fr;
/* 等價於 */
grid-template-columns: repeat(3, 1fr);
/* 第一列固定200px,剩餘空間按1:2分配 */
grid-template-columns: 200px 1fr 2fr;
/* 第一列按內容撐開,第二列佔1份,第三列佔2份 */
grid-template-columns: auto 1fr 2fr;
}💡 大白話:
fr就是「份」。1fr 2fr就是按 1:2 的比例分蛋糕。
2.3 repeat() 函數
當列數很多時,用 repeat() 更簡潔:
.grid {
display: grid;
/* 重複3次 1fr,等價於 1fr 1fr 1fr */
grid-template-columns: repeat(3, 1fr);
/* 重複4次 100px */
grid-template-columns: repeat(4, 100px);
/* 混合使用 */
grid-template-columns: 200px repeat(3, 1fr) 100px;
}2.4 auto-fit 和 auto-fill(自動列數)
這兩個值可以實現「自動響應式」,不需要寫媒體查詢!
.grid {
display: grid;
/* 自動適應:每列最少200px,放不下就換行 */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}這是 Grid 最強大的功能之一! 上面的代碼會:
- 屏幕寬時,自動多放幾列
- 屏幕窄時,自動減少列數
- 每列最少 200px,剩餘空間均分
auto-fit 和 auto-fill 的區別:
auto-fit:空的格子會塌縮,讓現有格子撐滿auto-fill:保留空格子位置
💡 99% 的情況下用
auto-fit就對了!
2.5 grid-template-rows(定義行)
和 grid-template-columns 類似,用來定義行的高度:
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
/* 3行,第一行100px,第二行200px,第三行100px */
grid-template-rows: 100px 200px 100px;
/* 第一行按內容,第二行佔滿剩餘 */
grid-template-rows: auto 1fr;
}💡 大多數情況下,行高不需要手動定義,讓內容自動撐開就好。
2.6 gap(間距)
和 Flexbox 一樣,Grid 也可以用 gap 設置間距:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px; /* 行列間距都是16px */
/* 或者分別設置 */
row-gap: 20px; /* 行間距 */
column-gap: 16px; /* 列間距 */
}三、網格線(Grid Lines)
3.1 什麼是網格線?
Grid 會自動給每條線編號,從 1 開始:
1 2 3 4
│ │ │ │
1 ├───────┼───────┼───────┤
│ 1 │ 2 │ 3 │
2 ├───────┼───────┼───────┤
│ 4 │ 5 │ 6 │
3 └───────┴───────┴───────┘- 列線:1, 2, 3, 4(從左到右)
- 行線:1, 2, 3(從上到下)
3.2 用網格線定位子元素
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px 100px;
}
/* 把 A 放到第2列到第3列,第1行到第2行 */
.item-a {
grid-column: 2 / 3; /* 從第2條線到第3條線 */
grid-row: 1 / 2; /* 從第1條線到第2條線 */
}
/* 把 B 放到第1列到第3列(跨2列),第2行到第3行 */
.item-b {
grid-column: 1 / 3; /* 跨2列 */
grid-row: 2 / 3;
}💡 大白話:
grid-column: 2 / 4意思是「從第 2 條線開始,到第 4 條線結束」,也就是佔了第 2 和第 3 兩列。
3.3 跨越的簡寫
/* 從第1列開始,跨3列 */
.item {
grid-column: 1 / span 3;
/* 等價於 */
grid-column: 1 / 4;
}
/* 從當前位置開始,跨2列 */
.item {
grid-column: span 2;
}💡 記憶技巧:
span N就是「跨越 N 個格子」。
四、網格區域(Grid Areas)
4.1 給區域命名
可以用名字來命名網格區域,非常直觀:
.layout {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 60px 1fr 40px;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}就像畫了一個表格:
┌──────────────────────────┐
│ header │
├──────────┬───────────────┤
│ sidebar │ content │
├──────────┴───────────────┤
│ footer │
└──────────────────────────┘4.2 使用命名區域
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.footer {
grid-area: footer;
}💡 這是 Grid 最直觀的用法! 畫個「ASCII 圖」就能定義佈局,一目瞭然。
4.3 用點號表示空區域
.grid {
grid-template-areas:
"header header header"
"sidebar . content"
"footer footer footer";
}中間的 . 表示這個位置留空。
4.4 響應式佈局(改變區域排列)
.layout {
display: grid;
grid-template-columns: 1fr;
grid-template-areas:
"header"
"content"
"sidebar"
"footer";
}
/* 大屏幕改成左右佈局 */
@media (min-width: 768px) {
.layout {
grid-template-columns: 200px 1fr;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
}💡 超方便! 只需要改
grid-template-areas就能切換佈局,HTML 完全不用動!
五、對齊方式
5.1 容器對齊(整體)
| 屬性 | 作用 | 類比 Flexbox |
|---|---|---|
justify-items | 子元素在格子內的水平對齊 | 無直接對應 |
align-items | 子元素在格子內的垂直對齊 | align-items |
justify-content | 整個網格在容器內的水平位置 | justify-content |
align-content | 整個網格在容器內的垂直位置 | align-content |
.grid {
display: grid;
grid-template-columns: repeat(3, 100px);
height: 400px;
/* 每個格子內的子元素:水平居中 */
justify-items: center;
/* 每個格子內的子元素:垂直居中 */
align-items: center;
/* 整個網格水平居中 */
justify-content: center;
/* 整個網格垂直居中 */
align-content: center;
}5.2 子元素對齊(單獨)
.item {
/* 單獨設置這個元素在格子內的水平對齊 */
justify-self: start; /* 或 center / end / stretch */
/* 單獨設置這個元素在格子內的垂直對齊 */
align-self: center;
}5.3 對齊速查表
justify-* = 水平方向(左右)
align-* = 垂直方向(上下)
*-items = 設置所有子元素
*-content = 設置整體網格
*-self = 設置單個子元素六、實戰練習
6.1 練習一:經典網頁佈局
<div class="layout">
<header class="header">頭部導航</header>
<aside class="sidebar">側邊欄</aside>
<main class="content">主要內容區</main>
<footer class="footer">底部版權</footer>
</div>.layout {
display: grid;
min-height: 100vh;
grid-template-columns: 240px 1fr;
grid-template-rows: 60px 1fr 40px;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
.header {
grid-area: header;
background: #1a1a2e;
color: white;
display: flex;
align-items: center;
padding: 0 20px;
}
.sidebar {
grid-area: sidebar;
background: #16213e;
color: white;
padding: 20px;
}
.content {
grid-area: content;
background: #f5f5f5;
padding: 24px;
}
.footer {
grid-area: footer;
background: #1a1a2e;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
/* 響應式:小屏幕改成上下排列 */
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"content"
"sidebar"
"footer";
}
}6.2 練習二:響應式相冊
<div class="gallery">
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
</div>.gallery {
display: grid;
/* 核心:一行代碼實現響應式! */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
padding: 16px;
}
.photo {
aspect-ratio: 1; /* 正方形 */
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
}💡 亮點:不管屏幕多寬多窄,相冊都會自動調整每行的照片數量,每張照片至少 200px 寬!
6.3 練習三:儀表盤佈局
<div class="dashboard">
<div class="card stats">統計概覽</div>
<div class="card chart">圖表區域</div>
<div class="card table">數據表格</div>
<div class="card todo">待辦事項</div>
</div>.dashboard {
display: grid;
grid-template-columns: 2fr 1fr;
grid-template-rows: auto auto auto;
gap: 16px;
padding: 16px;
}
.stats {
/* 跨兩列 */
grid-column: 1 / -1; /* -1 表示到最後一條線 */
background: #e3f2fd;
}
.chart {
/* 佔據第一列,第二行 */
grid-column: 1;
grid-row: 2;
height: 300px;
background: #f3e5f5;
}
.table {
/* 佔據第一列,第三行 */
grid-column: 1;
grid-row: 3;
height: 200px;
background: #e8f5e9;
}
.todo {
/* 佔據第二列,跨第二和第三行 */
grid-column: 2;
grid-row: 2 / 4; /* 從第2行到第4行 */
background: #fff3e0;
}
.card {
border-radius: 8px;
padding: 16px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
font-weight: bold;
}┌──────────────────────────────┐
│ 統計概覽 │
├────────────────┬─────────────┤
│ │ │
│ 圖表區域 │ 待辦事項 │
│ │ │
├────────────────┤ │
│ │ │
│ 數據表格 │ │
│ │ │
└────────────────┴─────────────┘6.4 練習四:聖盃佈局
經典的「聖盃佈局」(Holy Grail Layout):
<div class="holy-grail">
<header>頭部</header>
<nav>導航</nav>
<main>主內容</main>
<aside>側邊欄</aside>
<footer>底部</footer>
</div>.holy-grail {
display: grid;
min-height: 100vh;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: 80px 1fr 60px;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
gap: 12px;
padding: 12px;
}
header { grid-area: header; background: #1a1a2e; color: white; }
nav { grid-area: nav; background: #16213e; color: white; }
main { grid-area: main; background: #f5f5f5; }
aside { grid-area: aside; background: #16213e; color: white; }
footer { grid-area: footer; background: #1a1a2e; color: white; }
/* 所有區域通用樣式 */
.holy-grail > * {
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
font-size: 18px;
font-weight: bold;
}
/* 響應式 */
@media (max-width: 768px) {
.holy-grail {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"nav"
"aside"
"footer";
}
}6.5 練習五:表單佈局
用 Grid 對齊標籤和輸入框:
<form class="form">
<label>用戶名</label>
<input type="text" placeholder="請輸入用戶名">
<label>郵箱</label>
<input type="email" placeholder="請輸入郵箱">
<label>個人簡介</label>
<textarea placeholder="請輸入簡介"></textarea>
<div></div>
<button type="submit">提交</button>
</form>.form {
display: grid;
grid-template-columns: 100px 1fr; /* 標籤100px,輸入框撐滿 */
gap: 12px 16px; /* 行間距12px,列間距16px */
max-width: 500px;
}
.form label {
text-align: right;
line-height: 36px; /* 和輸入框等高 */
}
.form input,
.form textarea {
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
}
.form textarea {
height: 80px;
resize: vertical;
}
.form button {
grid-column: 2; /* 按鈕放在第二列 */
justify-self: start; /* 靠左對齊 */
padding: 8px 24px;
background: #4a90d9;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
}七、高級技巧
7.1 minmax() 函數
設置列寬的範圍:
.grid {
display: grid;
/* 每列最少200px,最多1fr */
grid-template-columns: repeat(3, minmax(200px, 1fr));
/* 側邊欄最少200px,最多300px */
grid-template-columns: minmax(200px, 300px) 1fr;
}7.2 auto 關鍵字
讓行或列根據內容自動計算:
.grid {
display: grid;
/* 中間列根據內容撐開,兩邊均分 */
grid-template-columns: 1fr auto 1fr;
}7.3 嵌套 Grid
Grid 可以嵌套使用:
.outer {
display: grid;
grid-template-columns: 200px 1fr;
}
.sidebar {
/* 側邊欄內部也用 Grid */
display: grid;
grid-template-rows: auto auto auto;
gap: 8px;
}
.content {
/* 內容區用 Grid 做卡片列表 */
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}7.4 Grid + Flexbox 混合使用
實際開發中,Grid 和 Flexbox 經常配合使用:
/* Grid 負責整體佈局 */
.page {
display: grid;
grid-template-areas:
"header"
"main"
"footer";
grid-template-rows: 60px 1fr 40px;
min-height: 100vh;
}
/* Flexbox 負責頭部內部排列 */
.header {
grid-area: header;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
}💡 黃金法則:Grid 做「整體佈局」,Flexbox 做「局部排列」。
八、常見問題
8.1 Grid 和 Flexbox 該選哪個?
| 需求 | 推薦 |
|---|---|
| 一行或一列的排列 | Flexbox |
| 多行多列的網格 | Grid |
| 整頁佈局 | Grid |
| 導航欄、按鈕組 | Flexbox |
| 卡片居中 | Flexbox(更簡單) |
| 響應式相冊 | Grid(auto-fit 更方便) |
| 複雜表單對齊 | Grid |
8.2 為什麼 grid-template-areas 不生效?
/* 問題:名字不匹配 */
.grid {
grid-template-areas:
"header header"
"main main";
}
.header {
grid-area: header; /* ✅ 匹配 */
}
.main-content {
grid-area: main; /* ❌ 不匹配!grid-template-areas 裡寫的是 "main",但要確保完全一致 */
}解決: 確保名字完全一致,且每個區域必須是矩形。
8.3 為什麼子元素沒有在格子里居中?
/* 問題:Grid 默認 stretch(拉伸),但子元素有固定尺寸時不會居中 */
.grid {
display: grid;
grid-template-columns: 200px 200px;
}
.item {
width: 100px; /* 固定寬度,但不在格子中間 */
}
/* 解決:加對齊屬性 */
.grid {
display: grid;
grid-template-columns: 200px 200px;
justify-items: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}九、Grid 速查表
9.1 容器屬性
| 屬性 | 作用 | 常用值 |
|---|---|---|
display | 開啟網格佈局 | grid |
grid-template-columns | 定義列 | repeat(3, 1fr) |
grid-template-rows | 定義行 | 100px 1fr 60px |
grid-template-areas | 命名區域 | "header header" "sidebar main" |
gap | 間距 | 16px |
justify-items | 水平對齊(所有子元素) | center |
align-items | 垂直對齊(所有子元素) | center |
justify-content | 網格水平位置 | center |
align-content | 網格垂直位置 | center |
9.2 子元素屬性
| 屬性 | 作用 | 常用值 |
|---|---|---|
grid-column | 佔據的列 | 1 / 3 或 span 2 |
grid-row | 佔據的行 | 1 / 3 或 span 2 |
grid-area | 命名區域 | header |
justify-self | 單獨水平對齊 | center |
align-self | 單獨垂直對齊 | center |
9.3 常用單位
| 單位 | 含義 | 例子 |
|---|---|---|
px | 固定像素 | 200px |
fr | 按比例分配 | 1fr 2fr |
auto | 自動 | auto |
% | 百分比 | 50% |
minmax() | 範圍 | minmax(200px, 1fr) |
repeat() | 重複 | repeat(3, 1fr) |
9.4 最常用組合
| 場景 | CSS |
|---|---|
| 等寬3列 | grid-template-columns: repeat(3, 1fr) |
| 響應式網格 | grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) |
| 整頁佈局 | grid-template-areas: "header header" "sidebar main" "footer footer" |
| 跨列元素 | grid-column: 1 / -1 |
十、總結
回顧本教程的要點:
display: grid開啟網格佈局grid-template-columns定義列,最常用的單位是frrepeat()簡化重複列的定義auto-fit + minmax()一行代碼實現響應式網格grid-template-areas用畫圖的方式定義佈局,最直觀gap設置間距,行列可以分別設置- 網格線 用數字編號,
1 / 3表示從第1條線到第3條線 span N表示跨越 N 個格子- Grid 做整體佈局,Flexbox 做局部排列 是最佳實踐
-1表示最後一條網格線,grid-column: 1 / -1就是跨滿整行
掌握了 Flexbox 和 Grid,你就擁有了 CSS 佈局的全部武器庫!
相關閱讀: