必须设 min-height: 100vh 并清除 html 和 body 的默认 margin,否则网格容器高度塌缩、1fr 失效、底部留白——这不是 Grid 写错了,是祖先链根本没撑开。

必须设 min-height: 100vh 并清除 html 和 body 的默认 margin,否则网格容器高度塌缩、1fr 失效、底部留白——这不是 Grid 写错了,是祖先链根本没撑开。
为什么 height: 100% 在全屏 Grid 中大概率失效
浏览器默认 html 和 body 高度由内容决定,不是视口。写 .grid { height: 100% } 时,它实际取的是 body 的高度;而 body 没显式设高,结果就是 0。所有后续的 grid-template-rows: auto 1fr auto 都在“0 高度”里分配,自然看不见中间那块 1fr。
解决方式只有一条链:html → body → 根容器,三者都需:
-
margin: 0(尤其body默认有 8px 外边距,会撕开白边) -
min-height: 100vh(比height: 100vh更安全,内容超长时不裁剪) - 避免对
html或body直接设height: 100%—— 它不保证被识别为视口高度
grid-template-rows: auto 1fr auto 不铺满?先查容器有没有真高度
这个写法本身没问题,但 1fr 是按“剩余可用空间”分配的,不是魔法。如果父容器高度是 auto,那“剩余空间”就是 0,1fr 就塌成一条线。
立即学习“前端免费学习笔记(深入)”;
典型错误现场:
- 只给
.main设grid-area: "main",但忘了给根容器(比如body)设display: grid和min-height: 100vh - 在网格容器上加了
padding,压缩了内部可用空间,导致1fr分到的“剩余”变小 - 用了
align-content: start,把所有行挤在顶部,视觉上像没铺满
验证步骤:打开 DevTools,选中网格容器,看 computed height 是否为实际视口高度(如 720px)。不是?那就卡在祖先链某一层了。
移动端重叠或侧边栏收起,不能只调 grid-column
Grid 不会因为你改了某个子项的 grid-column: 1 就自动重排整个结构。想让桌面端的右侧 sidebar 在小屏时“浮在 main 上方”,仅靠移动位置会溢出或错位。
正确做法是重定义区域结构:
- 桌面端:
grid-template-areas: "header header" "main sidebar" - 移动端:
grid-template-areas: "header" "main" "sidebar",再用@media切换 - 若要真正重叠(比如 banner 图 + 文字层),两个元素都设
grid-area: "hero",靠声明顺序或z-index控制叠放,而不是靠定位模拟
背景图建议用 ::before 伪元素承载,并设 z-index: -1,避免遮挡内容又不破坏网格流。
Safari 地址栏缩放导致 100vh 抖动?换 100dvh
移动端 Safari 在地址栏收起/展开时会动态调整视口高度,100vh 会跟着跳变,造成布局闪烁。Chrome 105+ 和 Safari 16.4+ 已支持 dvh(dynamic viewport height),它始终取当前可视区域高度,更稳定。
稳妥写法:
body {
min-height: 100dvh;
min-height: -webkit-fill-available; /* iOS 旧版兜底 */
margin: 0;
}注意:100dvh 还没进所有浏览器的稳定支持列表,上线前务必实测目标机型。另外,1fr 在主体内嵌滚动时可能失效——记得给主体加 min-height: 0,否则它会拒绝收缩,导致内部 overflow-y: auto 失灵。


















