卡片底部的按钮永远对不齐,你还在用 JS 量高度——CSS subgrid 今年 3 月刚进 Baseline

同一排卡片,标题一行、两行的都有,底部的按钮就参差不齐——这个对齐问题,你十有八九是用 JS 量高度或者给每张卡固定行高硬扛过去的。其实 CSS 早在 2019 年就给了原生答案:subgrid,而它在 2026 年 3 月正式进入 Baseline Widely available,Firefox 71、Safari 16、Chrome 117 起全支持,全球覆盖已超过 90%。该把那段对齐脚本删掉了。

为什么嵌套网格天生对不齐

先说清楚病根。当你给容器加 display: grid,只有它的直接子元素会成为网格项,孙元素回归普通文档流。想让卡片内部也参与网格,你通常会把卡片本身再设成 display: grid——这就是所谓的「嵌套网格」。

问题在于:嵌套网格完全独立于父网格,也彼此独立。它们各自根据自身内容计算轨道尺寸,根本感知不到旁边的兄弟卡片。于是同一行里,A 卡标题占一行、B 卡标题占两行,两张卡各自的内部行高不一样,底部自然对不齐。

过去的解法都不体面:要么用 JS 遍历所有卡片量出最大高度再统一设死,要么给每个槽位固定 min-height,内容一多就溢出。维护成本高,还容易在字体加载、窗口缩放时抖动。

subgrid 做的事:不新建轨道,直接继承

给嵌套网格的 grid-template-columns 或 grid-template-rows 设成 subgrid,关键变化就一句话:它不再生成自己的轨道列表,而是复用父网格已经定义好的轨道。

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

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

父网格定义了三列,每张卡片横跨父网格的若干行;卡片内部设 grid-template-rows: subgrid 后,它的标题、正文、页脚就直接落在父网格的行轨道上。所有卡片共享同一套行高——标题对齐、正文同起点、页脚全部贴底,无论内容长短。

两个容易忽略的细节:

  • 间距会继承。父网格的 gap 会传进子网格,但子网格可以用自己的 gap 覆盖它。调试时打开 DevTools 的网格检查器,你会发现子网格线正好落在间距中央。
  • 网格线编号会重置。子网格内部的第 1 条列线就是子网格自己的第一条线,不继承父网格的编号。这反而是好事:组件无论被放在父网格的哪个位置,内部编号永远一致,可复用性更强。

具名网格线也可以从父网格传下来,子网格还能额外声明自己的线名:

.card {
  display: grid;
  grid-template-columns: subgrid [sub-a] [sub-b] [sub-c] [sub-d];
  grid-template-rows: subgrid;
}

唯一的坑:子网格维度不会自动生成隐式轨道

这是 subgrid 最容易被忽视、也最容易在生产翻车的一条规则:在设为 subgrid 的那个维度上,不会创建隐式轨道。

MDN 的例子很直白:子网格横竖都是 subgrid,内部塞 12 个元素却只有 10 个格子,多出的 2 个不会撑出新行——它们会被全部堆进最后一格。

所以实践准则是:当子项数量未知时,留一个维度用普通嵌套网格。

.card {
  display: grid;
  grid-template-columns: subgrid;      /* 列对齐父网格 */
  grid-auto-rows: minmax(100px, auto); /* 行仍按内容自动生成 */
}

删掉 grid-template-rows: subgrid,行轨道的隐式创建就恢复了,需要多少行生成多少行,只是这些行不再和父网格对齐。要不要对齐,取决于你的布局是否真的需要跨卡同步。

什么时候该用,什么时候别硬上

最佳场景其实就一类:兄弟元素之间需要内部对齐。

  • 卡片列表:标题 / 正文 / 页脚跨卡对齐,这是最高频的用途;
  • 表单:多个字段的 label 列宽统一,输入框起点自然对齐;
  • 表格式布局:没有 table 标签、但需要列宽一致的数据行;
  • 仪表盘组件:多个卡片的头部、内容、底部纵向对齐。

反过来,如果嵌套网格的布局是自成一体的,用普通独立网格更简单,没必要引入 subgrid。

浏览器支持不用再纠结:Chrome 117+、Firefox 71+、Safari 16+、Edge 117+,Subgrid 自 2026 年 3 月起 Baseline Widely available,生产可用。老浏览器用 @supports (grid-template-rows: subgrid) 做特性检测,降级到 Flexbox 即可——虽然失去跨卡对齐,但布局不会崩。

下一步

打开你项目里那段「遍历卡片量高度」的代码,先别急着删。用一层 @supports 包住新的 subgrid 写法:

@supports (grid-template-rows: subgrid) {
  .card { display: grid; grid-template-rows: subgrid; grid-row: span 3; }
}

跑一遍网格检查器,确认对齐符合预期,再把旧的 JS 对齐逻辑摘掉。一次改一个卡片列表,风险最小、收益最直观。

评论区

0 条评论

登录后可评论。

小鹿·界面实验室 667 阅读