cover

結論先講

Grid 是專門為二維佈局設計的(列 + 行同時對齊)。跟 Flexbox 的分工:

場景用 Flexbox用 Grid
一排元素排列(導覽、tab)
單一方向的動態列表
頁面主結構(header/nav/main/aside/footer)
Dashboard 網格卡片
雜誌式版面(跨列跨行)
簡單的兩欄佈局都可以都可以

一個判斷:你需要同時控制「第 X 列第 Y 行」的位置 → Grid。只控制一個方向 → Flexbox。


心智模型:畫格子

.container {
  display: grid;
  grid-template-columns: 200px 1fr 100px;  /* 三欄:固定、彈性、固定 */
  grid-template-rows: 80px 1fr 60px;       /* 三列:固定、彈性、固定 */
  gap: 16px;
}

產生這樣的格子:

┌─────────┬──────────────────┬────────┐
│ 80px    │                  │        │
├─────────┼──────────────────┼────────┤
│         │                  │        │
│ 1fr     │                  │        │
│         │                  │        │
├─────────┼──────────────────┼────────┤
│ 60px    │                  │        │
└─────────┴──────────────────┴────────┘
 200px     1fr                100px

子元素自動按順序填進格子。


fr 單位:彈性分配

fr = fraction(份)。分配剩餘空間:

.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;  /* 1:2:1 分配 */
}

假設容器寬 400px,間距 0:

  • 第一欄:100px(1/4)
  • 第二欄:200px(2/4)
  • 第三欄:100px(1/4)

混用固定跟彈性

grid-template-columns: 250px 1fr 1fr;

第一欄固定 250px(側欄),剩下空間兩欄平均分。


命名網格區域:grid-template-areas

最容易讀的寫法:

.layout {
  display: grid;
  grid-template-columns: 200px 1fr 150px;
  grid-template-rows: 60px 1fr 40px;
  grid-template-areas:
    "header  header  header"
    "nav     main    aside"
    "footer  footer  footer";
  gap: 16px;
}
 
.layout > header { grid-area: header; }
.layout > nav    { grid-area: nav; }
.layout > main   { grid-area: main; }
.layout > aside  { grid-area: aside; }
.layout > footer { grid-area: footer; }

HTML:

<div class="layout">
  <header>...</header>
  <nav>...</nav>
  <main>...</main>
  <aside>...</aside>
  <footer>...</footer>
</div>

網格 template 就是 ASCII 排版圖。新人讀 code 秒懂。

響應式:在 media query 改 template-areas

@media (max-width: 768px) {
  .layout {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "nav"
      "main"
      "aside"
      "footer";
  }
}

整個版面重排,不用改 HTML。


repeat() + minmax():響應式網格的神器

固定欄數

grid-template-columns: repeat(4, 1fr);
/* 等同 1fr 1fr 1fr 1fr */

最小寬度 + 自動欄數

grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

解讀:每欄最小 250px、最大 1fr(平均分)、空間夠就自動多一欄

不用 media query 就能響應式:

寬 1200px → 4 欄(每欄 300px)
寬 900px  → 3 欄(每欄 300px)
寬 600px  → 2 欄(每欄 300px)
寬 300px  → 1 欄(占滿)

auto-fit vs auto-fill

  • auto-fit:空欄被摺疊(可用空間給 item 撐大)
  • auto-fill:空欄保留(留白)

99% 情況你要的是 auto-fit


跨格子:grid-column / grid-row

讓單一元素跨多格:

.hero {
  grid-column: 1 / 4;  /* 從第 1 條線到第 4 條線,跨 3 欄 */
  grid-row: 1 / 3;     /* 跨 2 列 */
}
 
/* 或用 span */
.hero {
  grid-column: span 3;
  grid-row: span 2;
}

線的編號

1    2    3    4
│    │    │    │
├────┼────┼────┤  1
│    │    │    │
├────┼────┼────┤  2
│    │    │    │
├────┼────┼────┤  3

線永遠比欄/列多 1 條。


對齊屬性(跟 Flexbox 類似但有新玩意)

屬性作用放哪
justify-content整個網格在容器水平位置(容器有剩餘空間時)容器
align-content整個網格在容器垂直位置容器
justify-items每個 item 在自己格子裡的水平對齊容器
align-items每個 item 在自己格子裡的垂直對齊容器
justify-self / align-self單一 item 的對齊item
place-items: center速記:justify-items + align-items容器
place-content: center速記:justify-content + align-content容器

超簡單置中

.container {
  display: grid;
  place-items: center;
  min-height: 100vh;
}

一行搞定。Flexbox 還要兩行。


常見模式:3 個 Pattern

Pattern 1:Holy Grail Layout(聖杯佈局)

.layout {
  display: grid;
  grid-template: auto 1fr auto / 200px 1fr 150px;
  min-height: 100vh;
  grid-template-areas:
    "header header header"
    "nav    main   aside"
    "footer footer footer";
}

Pattern 2:響應式卡片網格

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
}

Pattern 3:儀表板(Dashboard)

.dashboard {
  display: grid;
  grid-template-columns: repeat(12, 1fr);  /* 12 欄系統 */
  gap: 16px;
}
.stat-card { grid-column: span 3; }   /* 每張卡 3 欄 */
.chart-wide { grid-column: span 6; }  /* 寬圖表 6 欄 */
.chart-full { grid-column: 1 / -1; }  /* 滿寬 */

1 / -1 = 從第 1 條線到最後一條(反向索引)。


Subgrid:讓子元素對齊父網格

CSS Grid Level 2 的新功能(Chrome 117+、Firefox 71+、Safari 16+):

.parent {
  display: grid;
  grid-template-columns: 200px 1fr 150px;
}
 
.child {
  grid-column: 1 / 4;
  display: grid;
  grid-template-columns: subgrid;  /* 繼承父網格的欄位 */
}

以前要用 flex + 各種 calc 才能做到的「巢狀對齊」,subgrid 直接搞定。


常見陷阱

陷阱 1:item 內容超出格子

.item {
  min-width: 0;
  overflow: hidden;
}

跟 Flexbox 一樣,內容太長會撐破格子。

陷阱 2:auto 列高跟 1fr 的差別

grid-template-rows: auto 1fr auto;
  • auto:按內容高度
  • 1fr:吃剩餘空間

陷阱 3:grid 速記屬性容易搞混

grid: auto 1fr auto / 200px 1fr 150px;
/*     ↑ rows         ↑ columns */

/ 前是列,/ 後是欄。順序不能反。


實戰 Checklist

  • 頁面主結構用 Grid(不用多層 Flexbox)
  • 響應式卡片用 repeat(auto-fit, minmax(Xpx, 1fr))
  • grid-template-areas 讓版面圖直接在 CSS 可讀
  • gap 管間距
  • 置中用 place-items: center
  • 超出邊界用 min-width: 0overflow: hidden

相關文章