Learning Objectives
- 說明 Grid 同時處理欄與列兩個方向,並用 display: grid 與 grid-template-columns 建立格子版面
- 用 fr 單位與 repeat() 分配欄寬,算出固定寬度與 fr 混用時每一欄的寬度
- 用 gap 設定欄與列之間的間距
- 依格線編號(含負數)用 grid-column、grid-row 與 span 放置項目
- 說明項目超出明確格線時會自動產生隱式格線,並用 grid-auto-rows 控制它們的高度
同時排欄和列
Flexbox 一次只管一個方向:排成一列,放不下才換行,換行之後每一行各排各的,上下不一定對齊。
可是有很多版面本來就是格子:相簿、作品集、課表、商品列表、儀表板。 你要的是「三欄、每欄一樣寬、上下也對齊」,有時候某一格還要橫跨兩欄。這種同時管欄(column)和列(row)的版面, 用 CSS Grid(格線版面,CSS Grid Layout)最直接。目前主流瀏覽器都支援。
| Flexbox | Grid | |
|---|---|---|
| 管幾個方向 | 一個(主軸) | 兩個(欄與列) |
| 誰決定大小 | 通常由內容決定,項目伸縮去填空間 | 通常先畫好格子,再把項目放進去 |
| 適合 | 導覽列、按鈕列、一排卡片 | 相簿、整頁版型、表單的欄位對齊 |
這一課學怎麼畫格子、怎麼依格線編號放項目;下一課學用名稱畫整頁版型,以及不用媒體查詢也會自動換列的卡片牆。
display: grid、欄寬與 fr
和 Flexbox 一樣,設定寫在容器上,直接子元素變成 grid 項目(grid item):
.gallery {
display: grid;
grid-template-columns: 200px 1fr 2fr; /* 三欄:寫幾個值就是幾欄 */
gap: 12px; /* 欄與列之間的間距,和 Flexbox 的 gap 一樣 */
}
項目會依 HTML 的順序,從左到右、由上往下一格一格填進去,一列填滿就換下一列。
fr(fraction,份數)是 Grid 專用的單位:先扣掉固定寬度和 gap,剩下的再按份數分。 上面的例子如果容器寬 624px:
| 步驟 | 計算 |
|---|---|
| 扣掉固定寬度與 gap | 624 − 200 − 12 × 2 = 400px |
| 總份數 | 1 + 2 = 3 份,1fr = 400 ÷ 3 ≈ 133.3px |
| 三欄的寬度 | 200px、133.3px、266.7px |
重複的值用 repeat() 簡寫:repeat(3, 1fr) 就是 1fr 1fr 1fr,repeat(2, 100px 1fr) 是 100px 1fr 100px 1fr。
列也一樣用 grid-template-rows 設定,例如 grid-template-rows: 80px auto。沒有設定時,每一列的高度由內容決定(auto)。
為什麼不全部用百分比?
33.33%加上 gap 會超過 100%;fr分的是扣掉 gap 之後的空間,不必自己算。
格線編號與放置項目
Grid 用格線(grid line)定位:三欄的格子有 4 條直的格線,編號 1、2、3、4;兩列的格子有 3 條橫的格線。 欄與列之間的 gap 就落在格線上。
項目可以指定從哪條線開始、到哪條線結束:
.item-1 { grid-column: 1 / 3; } /* 從第 1 條直線到第 3 條:占兩欄 */
.item-1 { grid-column: span 2; } /* 效果相同:從自動排到的位置開始,橫跨 2 欄 */
.item-6 { grid-column: 2 / -1; } /* 從第 2 條到最後一條 */
.item-6 { grid-row: 3; } /* 放在第 3 列(從第 3 條橫線到第 4 條) */
| 寫法 | 意思 |
|---|---|
grid-column: 2 / 4 |
從第 2 條直線到第 4 條 |
grid-column: 2 / span 2 |
從第 2 條開始,橫跨 2 欄(到第 4 條) |
grid-column: 1 / -1 |
從第一條到最後一條:占滿整列,欄數改了也不用改 |
grid-row: 1 / 3 |
從第 1 條橫線到第 3 條:占兩列 |
負數從尾端倒數:-1 是最後一條、-2 是倒數第二條。要注意,負數只算明確格線,也就是 grid-template-columns/rows 畫出來的那些。
隱式格線(implicit grid):你只畫了 3 欄,卻放了 7 個項目,第三列從哪裡來?Grid 會自動多開列來放,這些自動產生的就是隱式格線。
它們的高度預設由內容決定,要統一高度就用 grid-auto-rows:
.gallery {
grid-template-columns: repeat(3, 1fr); /* 只畫欄 */
grid-auto-rows: 100px; /* 自動多出來的每一列都是 100px */
}
小測驗:欄寬與格線
容器寬 400px、沒有 gap,grid-template-columns: 100px 1fr 2fr。第三欄有多寬?
grid-template-columns: repeat(3, 1fr) 的格子,直的格線有幾條?
repeat(4, 1fr) 等於下面哪一個?
小測驗:放置項目與隱式格線
grid-column: 2 / span 2 讓項目占哪一段?
容器只設定 grid-template-columns: repeat(3, 1fr),裡面放 7 個項目。結果是?
grid-column: 1 / -1 的 -1 指的是哪一條格線?
重點整理
display: grid寫在容器上;grid-template-columns寫幾個值就是幾欄,grid-template-rows設定列。fr分的是扣掉固定寬度與 gap 之後的空間;repeat(3, 1fr)=1fr 1fr 1fr。gap設定欄與列之間的間距。- 格線從 1 開始編號,n 欄有 n+1 條直線;負數從明確格線的尾端倒數,
1 / -1占滿整列。 grid-column/grid-row寫「起點 / 終點」或span 數量。- 項目放不下時會自動產生隱式格線,用
grid-auto-rows統一它們的高度。
下一課用名稱畫出整頁版型(grid-template-areas),做出不寫媒體查詢也會自動換列的卡片牆,並整理 Flexbox 和 Grid 該怎麼選。