跳到主要内容

Grid 常见示例、坑点与调试

常见布局示例

1. 两栏应用布局

.app {
display: grid;
grid-template-columns: 280px minmax(0, 1fr);
min-height: 100vh;
}

.main {
min-width: 0; /* 关键:允许主内容收缩 */
}

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

minmax(0, 1fr)min-width: 0 双保险,避免长文本、代码块或不可收缩内容撑破主内容列。

2. 经典圣杯布局

.page {
display: grid;
grid-template:
"header header header" auto
"nav main aside" 1fr
"footer footer footer" auto
/ 200px minmax(0, 1fr) 240px;
min-height: 100vh;
}

一段 grid-template 同时表达了区域、行高和列宽,结构一目了然。

3. 卡片末尾按钮对齐

.card-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}

.card {
display: grid;
grid-template-rows: auto 1fr auto; /* 标题 / 正文弹性 / 按钮 */
}

即使每张卡片正文长度不同,第三行的按钮也能靠底对齐。(想让不同卡片之间也严格对齐,需要 subgrid。)

4. 元素居中

.container {
display: grid;
place-items: center; /* 水平 + 垂直居中 */
min-height: 100vh;
}

只居中单个子元素:

.item {
place-self: center;
}

5. 自适应表单

.form {
display: grid;
grid-template-columns: max-content minmax(0, 1fr);
gap: 12px 16px;
align-items: center;
}

.form label { justify-self: end; }

/* 占满一整行的字段(如多行文本框、提交按钮)*/
.form .full { grid-column: 1 / -1; }

@media (max-width: 600px) {
.form {
grid-template-columns: 1fr; /* 窄屏改为上下堆叠 */
}
.form label { justify-self: start; }
}

6. 图文重叠的 Hero 区

.hero {
display: grid;
}

.hero > * {
grid-area: 1 / 1; /* 全部放到同一格,形成重叠 */
}

.hero-text {
place-self: center;
z-index: 1;
}

这比 position: absolute 更安全:容器高度依然由最高的内容撑起,不会塌陷。

7. 顶栏底栏固定、中间独立滚动

.shell {
display: grid;
grid-template-rows: 56px minmax(0, 1fr) 48px;
height: 100dvh;
}

.shell-body {
overflow-y: auto; /* 配合 minmax(0, 1fr) 才能正确滚动 */
}

🔑 这里的 minmax(0, 1fr) 不可省。写成 1fr 时,行的最小高度会被内容撑开,overflow-y: auto 不会生效,变成整页滚动。

容易踩坑的细节

1fr 仍然可能溢出

Grid Item 默认的最小尺寸相当于 min-width: auto,会尊重内容的最小宽度。长 URL、pre、表格都可能撑破轨道。

/* 三道保险,按需叠加 */
.container { grid-template-columns: 240px minmax(0, 1fr); }
.main { min-width: 0; }
.content { overflow-wrap: anywhere; }

height: 100% 不一定生效

百分比高度依赖包含块已有明确高度。页面级布局更常用:

.page {
min-height: 100vh;
min-height: 100dvh; /* 支持 dvh 的浏览器会覆盖上一行 */
}

dvh 会动态考虑移动端地址栏伸缩,100vh 作为兼容回退。

Grid Item 的 z-index

Grid Item 即使没有设置 position,也可以直接用 z-index 控制重叠层级:

.hero-image { grid-area: 1 / 1; }
.hero-text { grid-area: 1 / 1; z-index: 1; }

DOM 顺序与视觉顺序

通过网格线、命名区域、orderdense 改变视觉位置,不会同步改变 DOM、阅读和键盘焦点顺序。先保证 HTML 顺序符合语义,再用 Grid 做视觉布局。

Grid 与绝对定位

绝对定位元素脱离正常的 Grid 自动布局,但如果它的包含块是 Grid Container(容器设了 position: relative),仍可用网格线确定定位区域:

.container { position: relative; display: grid; }
.badge { position: absolute; grid-area: 2 / 3; }

除装饰性重叠外,应优先让内容留在正常网格流中。

gap 不能用百分比叠加在溢出计算上

/* ❌ 100% 已经吃满,gap 只能往外溢 */
grid-template-columns: 50% 50%;
gap: 20px;

调试方法

  1. 在开发者工具中选中 Grid Container,开启 Grid Overlay(Chrome / Firefox 都内置)。
  2. 打开「显示线号」「显示区域名」「显示轨道尺寸」三个开关,直接对照 CSS 里写的编号。
  3. 看问题出在显式轨道还是浏览器生成的隐式轨道(Overlay 中隐式轨道的线为虚线)。
  4. 遇到溢出:依次检查 Item 默认最小尺寸、不可换行内容、固定宽度与百分比轨道。
  5. 遇到位置异常:检查结束线编号是否写多了一格,以及 grid-auto-flow: dense 是否改变了视觉顺序。
  6. 遇到高度异常:临时加 align-items: start 验证是不是默认 stretch 造成的。

快速描边法,能立刻看清实际网格划分:

* { outline: 1px solid rgba(255, 0, 0, .3); }

选择 Grid 的判断方式

满足任一条件时,优先使用 Grid:

  • 需要同时控制行和列。
  • 多个元素需要共享统一的轨道和对齐线。
  • 元素需要跨行、跨列或发生重叠。
  • 页面结构能清晰表达为命名区域。
  • 希望用 auto-fit + minmax() 构建无需媒体查询的响应式布局。

如果只需让一组元素沿一个方向排列、换行、对齐或分配空间,Flexbox 往往更简单。实际项目中,两者组合使用通常是最佳方案