应优先用100dvh替代100vh解决首屏露白或遮挡,但必须通过@supports(min-height: 100dvh)检测并回退至100vh;svh适用于固定底部按钮等需避开工具栏场景,lvh仅用于全屏沉浸页,三者不可混用,微信等不支持环境须JS fallback。

直接结论:用 100dvh 替代 100vh 是解决移动端首屏高度“露白”或“遮挡”的最简方案;但若需强稳定性(如支付按钮不被地址栏盖住),100svh 才是正确选择,100lvh 只适合全屏沉浸场景,且必须配合 min-height 或 max-height 使用。
为什么 height: 100vh 在手机上经常不准
因为 100vh 锁死的是页面加载那一刻的视口高度,而移动端浏览器的地址栏、底部工具栏会随滚动显隐——用户往下滚,地址栏收起,真实可视区域变高,但 100vh 元素没变,导致底部露出白底或内容错位。这不是 bug,是规范行为:CSS 的 vh 基于“布局视口”,不是“视觉视口”。
常见错误现象包括:
- 首屏轮播图容器设了
height: 100vh,真机下滑后底部空出 60px - 输入框在页面底部,键盘弹出时被盖住,
100vh容器没收缩 - 安卓 Chrome 滚动时工具栏自动隐藏,“跳一下”感明显,背景色和内容对不齐
100dvh 怎么用才真正动态响应
100dvh 是当前实时可视区域高度,地址栏收起就变高,展开就变矮,但它不能直接用于 height 属性——规范只允许它出现在 min-height、max-height、inset 等支持动态单位的属性中。
立即学习“前端免费学习笔记(深入)”;
实操建议:
- 写成
min-height: 100dvh或max-height: 100dvh,而非height: 100dvh;否则部分浏览器(如旧版 Safari)会忽略 - 搭配
height: auto使用,让内容撑开容器,避免因内容少导致高度塌陷 - 不要混用
dvh和svh:比如padding-bottom: 20svh+min-height: 100dvh,基准不同,结果不可控 - 检测兼容性必须用
@supports (min-height: 100dvh),@supports (height: 100dvh)永远为 false
100lvh 不是“更大的 dvh”,而是固定最大值
100lvh 表示地址栏强制隐藏时的最大可用高度,它不会随滚动实时变化,而是一个静态最大值。这意味着:
- 它适合全屏视频、Canvas 绘图等需要铺满物理屏幕的场景
- 但首次加载时如果地址栏还开着,
100lvh容器可能被顶部遮挡——必须加overflow: hidden或object-fit: cover配合处理 - 不能单独用
height: 100lvh,同样要走min-height或max-height;否则 iOS Safari 会退回到100vh - 安卓部分 WebView 对
lvh支持不稳定,建议加 JS fallback:监听resize事件,手动更新style.minHeight
容易被忽略的关键点
动态视口单位不是“写了就完事”。iOS Safari 地址栏显隐触发的是 resize 事件,不是 scroll;只监听 scroll 的 JS 方案完全失效。微信内置浏览器至今不支持任何动态单位,必须用 JS 计算 window.innerHeight 并注入 style。另外,dvh 频繁变化可能引发重排,对长列表或动画密集页要谨慎使用 min-height: 100dvh,优先考虑 svh + 安全区适配组合。


















