跳到主要内容

Grid 注意事项与常见坑

1. minmax 最小轨道在小屏溢出

现象repeat(auto-fit, minmax(300px, 1fr)) 在 320px 宽设备出现横向滚动。

原因:轨道最小 300px 大于容器。

解法

grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));

2. 1fr 与最小内容尺寸

1fr 等价于 minmax(auto, 1fr) 的历史行为会影响「能不能比内容更窄」。长单词、大图可能撑破 fr 轨道。

.item { min-width: 0; } /* 或 overflow: hidden / auto */
/* 轨道侧 */
grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);

3. grid-template-areas 必须是矩形

同一区域名不能摆成 L / T 形,否则整段声明无效。

/* 无效示例概念:main 呈 L 形 */
/* 应拆成多个区域或改用线号定位 */

每行字符串代表一行,列数必须一致;用 . 占位空单元。


4. 隐式行高度失控

只定义了列、没定义行时,新增行走 grid-auto-rows(默认 auto)。等高卡片或虚拟滚动场景请显式:

grid-auto-rows: minmax(120px, auto);
/* 或 */
grid-auto-rows: 1fr; /* 需容器有明确高度才有「分份」意义 */

5. 百分比、fr 与 gap 混用的心智负担

gap 会从容器中先扣除再分 fr。用 % 列宽 + gap 时,总和可能超过 100% 导致溢出。优先 fr + gap,少用「多列百分比相加 = 100%」老套路。


6. 滚动只出现在某一网格区域

与 Flex 类似,需要:

.page {
height: 100vh;
display: grid;
grid-template-rows: auto 1fr;
}
.main {
min-height: 0; /* 关键 */
overflow: auto;
}

min-height: 0(或 minmax(0, 1fr) 轨道)时,1fr 行往往被内容撑开。


7. dense 打乱阅读顺序

grid-auto-flow: dense 会回填空洞,视觉顺序可能与 DOM/Tab 不一致。装饰性瀑布可接受;表单、文章、结账流程慎用。


8. 只有直接子元素是 grid 项

包装多一层就不再占据你定义的 area。用 display: contents 可让子级「穿透」成为网格项,但要注意无障碍与浏览器差异,慎用。


9. align/justify 名字易混

目标
所有项目在各自单元格内justify-items / align-items
单个项目justify-self / align-self
整个网格在容器内(有多余空间时)justify-content / align-content

Flex 里没有 *-items 对「单元格」这层,从 Flex 转 Grid 时最容易混。


10. 媒体查询与 areas 不同步

改了 grid-template-areas 却忘了改子项 grid-area 名称,或桌面 areas 有 aside、移动删除后未重置,会导致元素不显示或叠在错误位置。断点切换时做一次「名称对照表」。


11. 性能

  • 超大网格(成百上千格)+ 频繁变更模板成本高,列表虚拟化优先
  • 动画避免连续改 grid-template-columns 长字符串;可动画 transform 或用固定模板 + 改 span
  • DevTools 打开 Grid 调试层检查线号,避免盲调

12. 与 Flex 嵌套时的职责

反模式:外层 Flex 硬模拟二维对齐。更清晰的分工:

  • Grid:页面/区块二维结构
  • Flex:导航、按钮组、卡片脚注对齐

快速自检表

  • 小屏是否用了 min(100%, …) 保护 minmax
  • 可收缩轨道/项目是否 minmax(0, 1fr) / min-width: 0
  • areas 每行列数一致且为矩形
  • 滚动容器链上有 min-height: 0
  • 未在关键路径滥用 dense / order
  • gap 与百分比列未叠加溢出

稳妥默认

.stack-grid {
display: grid;
gap: 1rem;
}
.responsive-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
gap: 1rem;
}
.app-shell {
display: grid;
grid-template-rows: auto minmax(0, 1fr);
height: 100vh;
}
.app-shell > main {
overflow: auto;
min-height: 0;
}