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;
}