结论是:dvh响应实时视口变化,svh保底防遮挡,lvh铺满最大区域,三者语义不同、不可互替;100vh在移动端出问题因其静态计算、不随地址栏或键盘状态变化,导致内容裁切、错位或留白。

直接说结论:用 dvh 响应浏览器 UI 实时变化(比如地址栏收起、键盘弹出),用 svh 保底防遮挡,用 lvh 铺满最大可用区域——三者不是替代关系,而是针对不同“视口状态”的明确选择。
为什么 100vh 在手机上经常出问题
移动端的 vh 是静态计算的:它基于页面加载那一刻的视口高度,不感知后续变化。一旦用户滚动(地址栏隐藏)、聚焦输入框(键盘弹出),实际可视区域变大或变小,100vh 却还按老尺寸渲染,结果就是内容被裁切、错位、或底部留白。
常见错误现象包括:
- 全屏卡片在滚动后“上移”,露出底部空白
- 固定定位的底部操作栏在键盘弹出时突然变矮甚至消失
- CSS 动画中用
vh做位移基准,动画过程出现跳动
dvh 是怎么做到“动态”的
dvh 的值随浏览器当前 UI 状态实时重算:地址栏展开时取较小值,收起时取较大值,键盘弹出时立即响应缩小后的高度。它不是靠 JS 监听 resize 或 scroll 模拟出来的,而是浏览器原生支持的 CSS 单位。
使用场景很明确:
- 需要元素始终贴合“当前可见区域”底部(如聊天输入框)
- 模态框/弹层高度要避免被键盘遮挡
- 全屏轮播或视频容器需保持视觉完整性
注意:dvh 在 Safari 16.4+、Chrome 105+、Firefox 112+ 支持良好,但旧版 iOS Safari(vh,需加降级样式。
svh 和 lvh 不是“动态”,而是“确定性边界”
svh 和 lvh 都是静态单位,但它们的基准不同:
-
svh= “Small Viewport Height”:假设所有浏览器 UI(地址栏、工具栏)都处于展开状态时的视口高度。这是最保守的值,适合防止内容被 UI 遮挡。 -
lvh= “Large Viewport Height”:假设所有可收缩 UI 都已完全隐藏时的视口高度。这是理论最大值,适合铺满整个屏幕(如启动页、引导页)。
关键差异在于稳定性:svh 和 lvh 不会随滚动或键盘触发重排,所以性能开销比 dvh 更低;但它们也不具备自适应能力——lvh 在地址栏展开时可能让内容溢出,svh 在地址栏收起时又显得太“矮”。
实际项目中怎么选、怎么写
没有万能解法,得看需求优先级:
- 要“稳”:优先用
svh(比如表单页顶部标题栏,必须始终可见) - 要“满”:用
lvh(比如 splash screen,必须撑满设备物理屏幕) - 要“活”:用
dvh(比如带输入框的对话界面,键盘弹出不能影响布局)
兼容性处理建议直接写两行:
section.fullscreen {
height: 100vh; /* fallback for older browsers */
height: 100dvh; /* modern dynamic behavior */
}
别指望一个单位通吃所有场景——dvh 的“动态”本质意味着它可能在某些动画帧里微小抖动,而 svh/lvh 的“静态”反而在特定时刻更可控。真正容易被忽略的是:这三个单位在横竖屏切换时都会重新计算,但 dvh 还多一层“键盘生命周期”的干扰,测试时务必真机连键盘操作几遍。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











