Learning Objectives
- 用 grid-template-areas 以文字畫出頁首、側欄、主內容、頁尾的整頁版型,並用 grid-area 把元素放進區域
- 說明區域名稱的規則:每列格數相同、同名區域要是長方形、用 . 表示空格
- 用 repeat(auto-fit, minmax()) 做出不寫媒體查詢也會依寬度自動換列的卡片牆,並分辨 auto-fit 與 auto-fill
- 用 place-items: center 讓內容在格子裡水平、垂直置中
- 依「一維或二維」「內容決定或版面決定」判斷該用 Flexbox 還是 Grid
用名稱畫出整頁版型
上一課用格線編號放項目:grid-column: 1 / -1、grid-row: 2。格子一多,數字就不好讀,
半年後再打開 CSS,很難一眼看出「側欄在哪裡」。
一般網頁的整體結構其實就那幾塊:頁首(header)、側欄(sidebar)、主內容(main)、頁尾(footer)。 Grid 讓你直接在 CSS 裡用名稱「畫」出這張配置圖:
.page {
display: grid;
grid-template-columns: 160px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
一眼就看得出來:頁首占滿第一列,第二列左邊側欄、右邊主內容,頁尾占滿最後一列。 這一課也會做出另一個常用版型:卡片牆,視窗變窄時卡片自動從四欄變成兩欄、一欄,不用寫任何媒體查詢。
grid-template-areas 的寫法
兩個步驟:
- 容器用
grid-template-areas畫配置圖:每一列是一個用引號包起來的字串,字串裡用空格分開每一格的名稱。 - 每個項目用
grid-area說自己是哪一塊。
.page {
display: grid;
grid-template-columns: 160px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
header { grid-area: header; }
nav { grid-area: sidebar; }
main { grid-area: main; }
footer { grid-area: footer; }
規則:
| 規則 | 說明 |
|---|---|
| 每一列的格數要一樣 | 上面每個字串都是 2 格;有一列寫成 3 格,整個宣告無效 |
| 同名的格子要排成長方形 | 寫成 L 形或分開兩處,整個宣告無效 |
用 . 表示空格 |
"header ." 表示右上角留空 |
| 欄寬、列高另外設定 | 名稱只決定位置,寬度仍由 grid-template-columns/rows 決定 |
只改 CSS 就能換版面:把 "sidebar main" 改成 "main sidebar",側欄就到右邊,HTML 一行都不用動。
不過要記得上一課的提醒:畫面上換位置不會改變閱讀與鍵盤順序,內容真正的先後還是由 HTML 決定。
自動換列的卡片牆:auto-fit 與 minmax()
商品、社團、作品這類卡片列表,希望寬螢幕排四五欄、手機排一欄。不用媒體查詢,一行就做得到:
.wall {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 12px;
}
拆開來看:
| 片段 | 意思 |
|---|---|
minmax(160px, 1fr) |
每一欄最窄 160px,最寬 1fr(平分剩下的空間) |
repeat(auto-fit, …) |
欄數不寫死,能放幾欄就放幾欄(每欄至少 160px) |
容器 700px 寬時放得下 4 欄(4 × 160 + 3 × 12 = 676),就排 4 欄,再把多的空間平均撐開; 容器剩 330px 時只放得下 1 欄(2 欄需要 332px),就變成 1 欄。
auto-fit 和 auto-fill 都是「能放幾欄就放幾欄」,差別在項目比欄位少的時候:
| 空出來的欄位 | 結果 | |
|---|---|---|
auto-fill |
保留著(看不見的空欄) | 項目維持最小寬度附近,右邊留白 |
auto-fit |
收起來(寬度變 0) | 項目撐開,填滿整列 |
例如只有 2 張卡片放在 1000px 的容器裡:auto-fill 仍然切出 5 欄,2 張卡片各占一欄、右邊空 3 欄;auto-fit 把空欄收起來,2 張卡片各占一半。 卡片數量多到填滿一整列時,兩者看起來一樣。
小測驗:區域與自動換列
下面哪一個 grid-template-areas 是無效的?
配置圖從 "sidebar main" 改成 "main sidebar" 之後,下面哪一個敘述正確?
容器 1000px 寬,只有 2 張卡片,grid-template-columns: repeat(auto-fit, minmax(160px, 1fr))。兩張卡片多寬?
place-items 置中,以及 Flexbox 和 Grid 怎麼選
Grid 也能置中,而且只要兩行:
.empty {
display: grid;
place-items: center; /* 等於 align-items: center + justify-items: center */
}
place-items 是簡寫:第一個值給 align-items(列方向,垂直),第二個值給 justify-items(欄方向,水平),只寫一個就兩個都用。
它讓每個項目在自己的格子裡置中;只有一個子元素時,效果就是放在正中央。
Flexbox 和 Grid 怎麼選? 兩者不是互相取代,一個頁面常常同時用到:
| 問自己 | 偏向 Flexbox | 偏向 Grid |
|---|---|---|
| 要排幾個方向? | 一個方向(一列或一欄) | 兩個方向(欄與列要對齊) |
| 誰決定大小? | 內容決定,項目依內容伸縮 | 版面決定,先畫好格子再放內容 |
| 典型例子 | 導覽列、按鈕群組、標籤列、卡片內部 | 整頁版型、相簿、卡片牆、儀表板 |
常見的組合:整頁用 Grid 分出頁首、側欄、主內容;頁首裡面的 logo 和連結用 Flexbox 排成一列。
小測驗:置中與選擇工具
place-items: center 等於下面哪一組設定?
頁首裡有 logo、4 個連結和一個登入按鈕,連結的寬度依文字長短而不同,要排成一列。比較適合用?
整頁要分成頁首、側欄、主內容、頁尾,側欄和主內容要上下對齊頁首與頁尾的邊緣。比較適合用?
重點整理
grid-template-areas用字串畫配置圖,每列一個字串;項目用grid-area對到名稱。- 每列格數要一樣、同名區域要是長方形,
.表示空格;只改 CSS 就能換版面,但閱讀順序仍照 HTML。 repeat(auto-fit, minmax(160px, 1fr)):每欄至少 160px,能放幾欄放幾欄,不用媒體查詢也會換列。auto-fit收起空欄、項目撐開;auto-fill保留空欄。display: grid; place-items: center;讓內容在格子裡置中。- 一個方向、內容決定大小用 Flexbox;兩個方向、版面決定位置用 Grid;常常一起用。
下一課是響應式設計:viewport 設定、媒體查詢、行動版優先,以及用 clamp() 讓字級隨螢幕寬度平滑變化。