100vh + grid-template-rows 不能直接等分全屏,因fr依赖容器高度,而100vh受margin、box-sizing、iOS地址栏及缩放影响,需同时设置html/body高度、重置margin、border-box及容器height:100vh。

为什么100vh + grid-template-rows 不能直接等分全屏
因为100vh是视口高度,但grid-template-rows: 1fr 1fr 1fr这类写法本身不依赖vh——它靠的是容器高度。如果父容器没设高,fr单位就“没地方可分”。很多人写了height: 100vh在 grid 容器上,却忘了它可能被 margin、滚动条或 box-sizing 拖累。
-
100vh在 iOS Safari 中会把地址栏高度算进去,缩放时可能跳变 - 如果 body 有默认 margin 或未重置
box-sizing,容器实际高度会小于预期 -
grid-template-rows: repeat(3, 1fr)和1fr 1fr 1fr行为一致,但前者更易维护;别用auto或minmax()混搭,容易打破等分逻辑
必须设置的三处 CSS 才能稳定等分
只写 display: grid 和 grid-template-rows 不够,缺一不可:
- 给 grid 容器加
height: 100vh(或min-height: 100vh,更安全) - 确保它从
html和body继承满高:html, body { height: 100%; margin: 0; } - 设
box-sizing: border-box在根或容器上,避免 padding 把内容挤出视口
示例最小可用结构:
html, body {
height: 100%;
margin: 0;
}
body {
box-sizing: border-box;
}
.grid-container {
display: grid;
height: 100vh;
grid-template-rows: repeat(3, 1fr);
}
滚动时内容溢出导致等分失效的典型场景
当某一个网格项里文字太多、图片没约束、或子元素用了 height: 100% 却没继承上下文高度,就会撑开容器,1fr 失去参照,等分崩坏。
立即学习“前端免费学习笔记(深入)”;
- 子项内避免用
height: 100%,改用height: 100vh或flex: 1配合内部 flex 布局 - 图片加
max-height: 100%; object-fit: contain;,否则原始尺寸可能突破网格行高 - 如果需要滚动某一块,给对应网格项加
overflow-y: auto和明确min-height: 0(防止 fr 单元格不收缩)
兼容性与替代方案提醒
100vh + grid 在 Chrome 66+、Firefox 63+、Safari 14.1+ 稳定,但 Safari 13.1 及更早版本对 100vh 在横屏/地址栏收起时计算不准。
- 如需支持老 Safari,可用 JS 动态设
style.height = window.innerHeight + 'px'并监听resize - 不用 Grid 的话,
flex+flex: 1也能等分,但语义和响应行为略有差异:Grid 更适合二维布局,Flex 更适合单轴流式伸缩 -
100dvh是新标准(已进 Chrome 105+),能避开地址栏干扰,但目前仅 Chromium 系和 Safari 16.4+ 支持,别直接替换100vh
真正卡住人的往往不是语法,而是 100vh 被谁吃了高度、fr 被谁抢了参照、以及移动端那个永远不肯老实的地址栏










