CSS 網格佈局 Grid
Grid 基本概念
什麼是 Grid?
CSS Grid 是一個二維的佈局系統,可以同時處理行(rows)和列(columns)。與 Flexbox 的一維佈局不同,Grid 能夠創建複雜的網格結構,非常適合用於整體頁面佈局。
Grid 容器與項目
- Grid Container: 設定
display: grid或display: inline-grid的父元素 - Grid Items: Grid Container 的直接子元素
- Grid Line: 構成網格結構的分隔線(水平和垂直)
- Grid Track: 兩條相鄰網格線之間的空間(行或列)
- Grid Cell: 四條網格線圍成的最小單位
- Grid Area: 由多個 Grid Cell 組成的矩形區域
Grid 結構示意圖:
┌─────────┬─────────┬─────────┐
│ Cell 1 │ Cell 2 │ Cell 3 │ ← Grid Track (Row)
├─────────┼─────────┼─────────┤
│ Cell 4 │ Cell 5 │ Cell 6 │
├─────────┼─────────┼─────────┤
│ Cell 7 │ Cell 8 │ Cell 9 │
└─────────┴─────────┴─────────┘
↑ ↑ ↑
Grid Track (Column)
Grid Container 屬性
1. display
啟用 Grid 佈局:
.container {
display: grid; /* 或 inline-grid */
}
2. grid-template-columns / grid-template-rows
這兩個屬性是 Grid 佈局的核心,用於定義網格的列(columns)和行(rows)結構。你可以使用多種單位和函數來創建靈活的網格系統。
.container {
/* 固定寬度:創建三個各 200px 寬的列 */
grid-template-columns: 200px 200px 200px;
/* 使用 fr 單位(fraction,分數單位):按比例分配空間 */
grid-template-columns: 1fr 2fr 1fr; /* 1:2:1 的比例,第二列是第一列的兩倍寬 */
/* 混合使用:結合固定寬度和彈性寬度 */
grid-template-columns: 200px 1fr 2fr; /* 第一列固定 200px,剩餘空間按 1:2 分配 */
/* 使用 repeat() 函數:避免重複書寫 */
grid-template-columns: repeat(3, 1fr); /* 等同於 1fr 1fr 1fr */
grid-template-columns: repeat(2, 100px 1fr); /* 等同於 100px 1fr 100px 1fr */
/* 響應式網格:自動填充列 */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* auto-fill 會盡可能多地創建列,每列最小 200px,最大 1fr */
/* 定義行高 */
grid-template-rows: 100px auto 100px; /* 第一行 100px,第二行自動,第三行 100px */
grid-template-rows: repeat(3, 150px); /* 三行各 150px */
}
fr 單位代表網格容器中可用空間的一個分數(fraction)。
計算方式:
- 先扣除所有固定寬度(如 px、%)
- 剩餘空間按 fr 的比例分配
範例:容器寬度 1000px
grid-template-columns: 200px 1fr 2fr;
- 第一列:200px(固定)
- 剩餘空間:1000px - 200px = 800px
- 第二列:800px × (1/3) ≈ 267px
- 第三列:800px × (2/3) ≈ 533px
repeat() 函數可以簡化重複的網格定義:
語法:repeat(重複次數, 軌道大小)
特殊關鍵字:
auto-fill:盡可能多地創建軌道,即使沒有內容也會保留空軌道auto-fit:只創建需要的軌道,並讓現有軌道擴展填滿空間
範例:
/* 基本用法 */
repeat(3, 1fr) → 1fr 1fr 1fr
/* 複雜模式 */
repeat(2, 100px 1fr) → 100px 1fr 100px 1fr
/* 響應式 */
repeat(auto-fit, minmax(250px, 1fr))
grid-template-columns 範例
選擇不同的 grid-template-columns 值觀察列的變化
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
gap: 10px;
justify-items: stretch;
align-items: stretch;
justify-content: start;
align-content: start;3. gap (row-gap, column-gap)
定義網格項目之間的間距:
.container {
gap: 20px; /* 行列間距都是 20px */
gap: 20px 10px; /* 行間距 20px, 列間距 10px */
/* 或分別設定 */
row-gap: 20px;
column-gap: 10px;
}
gap 範例
調整 gap 值觀察網格項目間距變化
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
gap: 20px;
justify-items: stretch;
align-items: stretch;
justify-content: start;
align-content: start;4. justify-items
控制所有網格項目在其單元格內的水平對齊方式(行軸,inline axis)。這個屬性會影響容器內的所有項目,如果要單獨控制某個項目,請使用 justify-self。
.container {
justify-items: stretch; /* 預設值,拉伸填滿整個單元格寬度 */
justify-items: start; /* 靠單元格左側對齊 */
justify-items: end; /* 靠單 元格右側對齊 */
justify-items: center; /* 在單元格內水平置中 */
}
- stretch:項目會拉伸以填滿整個單元格(如果項目沒有設定固定寬度)
- start/end/center:項目保持其原始大小,並在單元格內對齊
justify-items 範例
調整 justify-items 觀察項目在單元格內的水平對齊
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
gap: 10px;
justify-items: stretch;
align-items: stretch;
justify-content: start;
align-content: start;5. align-items
控制所有網格項目在其單元格內的垂直對齊方式(塊軸,block axis)。與 justify-items 類似,但作用於垂直方向。
.container {
align-items: stretch; /* 預設值,拉伸填滿整個單元格高度 */
align-items: start; /* 靠單元格頂部對齊 */
align-items: end; /* 靠單元格底部對齊 */
align-items: center; /* 在單元格內垂直置中 */
}
- justify-items:控制水平方向(左右)的對齊
- align-items:控制垂直方向(上下)的對齊
- 兩者都作用於項目在單元格內的對齊,而非整個網格的對齊
align-items 範例
調整 align-items 觀察項目在單元格內的垂直對齊
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 120px);
gap: 10px;
justify-items: stretch;
align-items: stretch;
justify-content: start;
align-content: start;6. justify-content
控制整個網格在容器內的水平對齊方式。注意:這個屬性只在網格總寬度小於容器寬度時才會生效。
.container {
justify-content: start; /* 預設值,網格靠容器左側 */
justify-content: end; /* 網格靠容器右側 */
justify-content: center; /* 網格在容器內水平置中 */
justify-content: stretch; /* 拉伸網格填滿容器 */
justify-content: space-between; /* 網格兩端對齊,中間平均分配空間 */
justify-content: space-around; /* 每個軌道兩側有相等空間 */
justify-content: space-evenly; /* 所有間距完全相等 */
}
justify-content 只在以下情況生效:
- 網格軌道使用固定寬度(如
100px) - 網格總寬度小於容器寬度
如果使用 fr 單位,網格會自動填滿容器,此屬性不會有明顯效果。
space-between: |[軌道1]────[軌道2]────[軌道3]|
space-around: |──[軌道1]────[軌道2]────[軌道3]──|
space-evenly: |───[軌道1]───[軌道2]───[軌道3]───|
justify-content 範例
調整 justify-content 觀察整個網格的水平對齊(需要網格寬度小於容器)
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: auto;
gap: 10px;
justify-items: stretch;
align-items: stretch;
justify-content: start;
align-content: start;7. align-content
控制整個網格在容器內的垂直對齊方式。與 justify-content 類似,但作用於垂直方向,只在網格總高度小於容器高度時生效。
.container {
align-content: start; /* 預設值,網格靠容器頂部 */
align-content: end; /* 網格靠容器底部 */
align-content: center; /* 網格在容器內垂直置中 */
align-content: stretch; /* 拉伸網格填滿容器 */
align-content: space-between; /* 網格上下對齊,中間平均分配空間 */
align-content: space-around; /* 每個軌道上下有相等空間 */
align-content: space-evenly; /* 所有間距完全相等 */
}
這兩個屬性的差異:
| 屬性 | 作用對象 | 方向 | 生效條件 |
|---|---|---|---|
| justify-items | 單元格內的項目 | 水平 | 總是生效 |
| align-items | 單元格內的項目 | 垂直 | 總是生效 |
| justify-content | 整個網格 | 水平 | 網格寬度 < 容器寬度 |
| align-content | 整個網格 | 垂直 | 網格高度 < 容器高度 |
記憶口訣:
- items:控制項目在單元格內的對齊
- content:控制整個網格在容器內的對齊
align-content 範例
調整 align-content 觀察整個網格的垂直對齊
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 100px);
gap: 10px;
justify-items: stretch;
align-items: stretch;
justify-content: start;
align-content: start;8. grid-template-areas
使用命名的網格區域來定義佈局,這是 Grid 最強大且最直觀的功能之一。透過視覺化的方式定義佈局結構,讓程式碼更易讀易維護。
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header" /* 第一行:header 跨越 3 列 */
"sidebar main main" /* 第二行:sidebar 1 列,main 2 列 */
"footer footer footer"; /* 第三行:footer 跨越 3 列 */
}
/* 將元素指定到對應的區域 */
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
可以使用 . 來表示空白的單元格,創建更靈活的佈局:
grid-template-areas:
"header header header"
"sidebar main ." /* 右側留空 */
"footer footer footer";
多個連續的 . 可以合併:
grid-template-areas:
"header header header"
"sidebar main ..." /* 等同於 ". . ." */
"footer footer footer";
命名規則