CSS Grid 那些没人告诉你、但每天都在坑你的细节

我用 CSS Grid 大概有三年了,一直觉得它「简单」。直到上个月重构这个博客的样式,踩了一圈坑,才发现那些我以为懂了的东西,其实只懂了一半。

这篇不是入门教程。是把那些坑记下来,给同样用了很久、却没认真读过规范的人。

minmax 的上限会被内容撑破

这是最经典的一个。grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)) 看起来很美:最小 200px,最大平分。但如果你放进去的内容最小宽度超过 200px(比如一段很长且不换行的英文 URL、一段代码、一张固定宽度的图),轨道会被撑开,破坏整个网格。

解决办法有两个:给内容 min-width: 0,或者在 minmax 里用 minmax(min(200px, 100%), 1fr) 这种更保守的写法。后者在我这个站点上稳定得多。

隐式轨道的默认尺寸

当你放进去的项目数量超出显式定义的轨道,浏览器会自动创建隐式轨道。它的默认尺寸是 auto——也就是「由内容决定」。这在卡片布局里往往不是你想要的:卡片会高低不齐,甚至被某张特别高的图撑成一根柱子。

.grid { grid-auto-rows: minmax(180px, auto); }

显式约束隐式轨道,通常能让布局立刻好看一半。

auto-fill 与 auto-fit 的差别

这两个值我记了很多次,每次都会忘。简单说:auto-fill 会保留空的轨道位置(即使没内容也占位),auto-fit 会把空轨道折叠掉,让有内容的轨道展开填满。

用在响应式网格上,绝大多数情况你要的是 auto-fit:一行只剩一张卡片时,它会撑满整行,而不是缩在左边。

1fr 到底分的是什么

fr 分的是「剩余空间」,不是「总宽度」。这一点听起来显然,但当你混用 fr 和固定单位时就会出事:固定宽度先被扣除,剩下的才按比例分。如果固定部分比容器还宽,fr 那一侧可能直接变成 0。

这也是为什么响应式布局里,我会给 fr 侧的元素加 min-width: 0——防止它被内容撑爆导致溢出。

gap 不算在轨道里

这个坑很隐蔽。gap 是轨道之间的间隔,不包含在任何轨道尺寸的计算里。所以 grid-template-columns: 1fr 1fr; gap: 20px 的真实宽度是「各 50% 再加 20px 间隔」。在窄屏上这会溢出。

解决方式是把 gap 算进轨道,或者干脆在窄屏用媒体查询把 gap 调小。

grid 项的默认对齐

没设置的情况下,grid 子项会被拉伸(stretch)填满整个单元格。这通常是好事,但当你想要「内容多高就多高」时,得显式写 align-items: start。

我在这个站点的卡片布局里就踩过:卡片内部文字短的时候,整张卡片被拉得很高,看起来很怪。

什么时候该放弃 Grid

Grid 不是万能的。一维布局(比如导航条、工具栏、横向列表)用 flexbox 往往更省心:它天然处理不了的情况更少。我的经验是——

  • 需要精确的行与列对齐:Grid。
  • 需要内容自然流动、按需换行:flex 或 block。
  • 两者嵌套使用,比硬凑一种方案更干净。

读完规范之后

这篇其实是我读完一遍 Grid 规范之后的笔记。规范不长,但「读完」这件事本身,帮我省掉了之后无数次的试错。

如果你也用了很久却没读过,建议花一个周末。比你想象的值。