CSS Grid 实现响应式三栏布局(一行代码搞定 12 列网格)

flexbox 适合一维,CSS Grid 适合二维。"侧栏 + 主内容 + 副栏"经典三栏
布局用 Grid 写比 flex 简洁 5 倍。

1. 最简版

<div class="layout">
  <aside>侧栏</aside>
  <main>主内容</main>
  <section>副栏</section>
</div>
.layout {
  display: grid;
  grid-template-columns: 200px 1fr 280px;
  gap: 24px;
}

fr 是"剩余空间分数"。1fr 中间吃满,左右固定。

2. 窄屏自动折叠

.layout {
  display: grid;
  grid-template-columns: 200px 1fr 280px;
  gap: 24px;
}

@media (max-width: 1000px) {
  .layout {
    grid-template-columns: 200px 1fr;
  }
  .layout > section {
    grid-column: 1 / -1;   /* 副栏跨整行,垂直堆叠 */
  }
}

@media (max-width: 700px) {
  .layout {
    grid-template-columns: 1fr;
  }
}

grid-column: 1 / -1 是 Grid 的常用语法:从第 1 条线到最后一条线,
即占满全宽。

3. 命名区域(更清晰的多栏 / 多行)

.layout {
  display: grid;
  grid-template-columns: 200px 1fr 280px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header header"
    "sidebar main rail"
    "footer footer footer";
  gap: 16px;
  min-height: 100vh;
}

.layout > header  { grid-area: header; }
.layout > aside   { grid-area: sidebar; }
.layout > main    { grid-area: main; }
.layout > section { grid-area: rail; }
.layout > footer  { grid-area: footer; }

窄屏重排,只改 grid-template-areas

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

4. 12 列网格系统(不需要 Bootstrap)

.grid12 {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 20px;
}

.col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; }
.col-6 { grid-column: span 6; }
.col-12 { grid-column: span 12; }

@media (max-width: 800px) {
  .col-3, .col-4, .col-6 { grid-column: span 12; }
}
<div class="grid12">
  <div class="col-4">A</div>
  <div class="col-4">B</div>
  <div class="col-4">C</div>
  <div class="col-6">D</div>
  <div class="col-6">E</div>
</div>

整套不到 30 行 CSS,干掉 Bootstrap grid 一整个模块。

5. 让卡片网格自动决定列数(最常用!)

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}

auto-fill + minmax:每列最小 260px,最大平分;窗口宽就放多列、
窗口窄就放少列,不需要任何 media query。视口超过 4×260 时一行 4 个,
缩到 2×260 时一行 2 个。

6. 让子元素拉满高度

.cards { display: grid; grid-auto-rows: 1fr; ... }

grid-auto-rows: 1fr 让每行所有 cell 等高,再加 align-self: stretch
内部内容拉满。

7. subgrid(2024 + 浏览器全支持)

子元素的 grid track 对齐父元素:

.card {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3;   /* 跨父网格 3 行 */
}

适合"卡片列表里每张卡片内部各自有 header / body / footer,但希望同一行
卡片的 header / body / footer 严格对齐"。

8. DevTools

Chrome / Firefox 的 Inspector 里点 grid 标记会显示 grid 线条和 area 名字,
是调试 grid 唯一有效的方法。别盲调。

踩过的坑

  • minmax(260px, 1fr) 在窄屏(< 260px 视口)会撑破父容器;想严格防溢出
    minmax(min(260px, 100%), 1fr)
  • gap 在 Safari 14 之前的 flexbox 不支持,Grid 支持。如果用 flex
    老 Safari 兼容性差。
  • grid-template-areas 时 area 名要 每个 cell 都有 字符串。
    "header . header". 表示空。
  • 大量 grid 嵌套对老设备性能不友好。深嵌套 grid 时考虑用 contain: layout
    限制重排范围。
精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。