subgrid生效需同时满足三条件:父容器显式定义grid-template-rows、子元素为真实直系子项、子元素声明display: grid与grid-template-rows: subgrid;缺一即失效,开发者工具中计算值显示none即表明已丢弃。

subgrid 不是“开了就对齐”的开关,它只在父容器显式定义轨道、子元素为真实直系子项、且声明完整时才生效;多数人遇到的“没对齐”,其实是父没写 grid-template-rows 或中间夹了 display: contents 层。
为什么 grid-template-rows: subgrid 没效果
浏览器对 subgrid 的解析是硬性校验:缺任一条件,整条声明被静默丢弃。开发者工具里看到 grid-template-rows 计算值为 none,就说明已失效。
- 父容器只写了
grid-auto-rows: 100px或靠repeat(auto-fit, ...)动态生成轨道 → 没有“模板”,无法继承 - DOM 结构中存在
display: contents包裹层或fieldset等语义容器 → 子元素不再是父网格的直接子节点 - 子元素写了
display: grid却漏掉grid-template-rows: subgrid→ subgrid 不是 display 值,必须单独声明 - 父用了
gap,但子没用grid-row: span N显式占满对应行数 → 隐式轨道插入,破坏继承链
嵌套列表对齐必须满足的三层前提
让列表项(如 .card)内部的标题、摘要、按钮严格对齐顶层轨道,不是加一行 subgrid 就完事,而是三者缺一不可:
- 父容器(如
.list)设display: grid且显式声明grid-template-rows: auto 1fr auto(不能是auto-fit或minmax()) - 列表项(
.card)是.list的**真实 DOM 直接子元素**,中间不能有仅用于布局的 wrapper 或display: contents -
.card同时声明display: grid+grid-template-rows: subgrid+grid-row: span 3(必须匹配父轨道行数)
子元素怎么用父轨道定位
启用 grid-template-rows: subgrid 后,.card 自身仍是网格容器,它的子元素可直接使用父级的行线编号——不需要像素计算,也不依赖内容高度。
- 父定义了
grid-template-rows: auto 1fr auto→ 行线编号为1 / 2 / 3 / 4 -
.card h2写grid-row: 1,.card p写grid-row: 2,.card button写grid-row: 3 - 即使某张卡片没有
p,button仍落在第 3 行线之间,视觉位置完全一致 - 命名线也可复用:
.card label { grid-row: label; },前提是父已定义grid-template-rows: [label] auto [input] 1fr [hint] auto
响应式下怎么不打断继承链
subgrid 本身不响应,响应逻辑必须由父容器驱动;子层一旦自己写 @media 改轨道,继承就断了。
- 正确做法:所有断点都在父容器上改
grid-template-columns,例如@media (max-width: 768px) { .list { grid-template-columns: 1fr; } } - 错误做法:在
.card上写@media并修改grid-template-columns→ 它立刻变成独立网格,不再继承 - 若小屏需隐藏某行内容(如
.hint),用display: none,别用visibility: hidden—— 后者仍占轨道位,会撑高整行 - 避免在父容器中混用
gap和 subgrid 子项:若父设了gap: 1rem,子必须用grid-row: span 3覆盖全部行,否则 gap 会插入隐式轨道
真正难的不是敲出那行 grid-template-rows: subgrid,而是从 HTML 结构开始就保持干净:没有空文本节点、不用 display: contents 偷懒、父轨道定义稳定不靠自动计算——任何一处松动,整条继承链就无声断裂。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











