100vh在移动端跳变是因为其基于初始视口的静态计算,不响应工具栏显隐导致的可用高度变化;svh适用于需始终避开工具栏的场景(如底部按钮),lvh适用于追求最大沉浸空间的全屏页,二者均为固定锚点值,无跳变但不可通用替代dvh。

为什么100vh在移动端会跳变而不是平滑响应
因为100vh是基于初始布局视口(layout viewport)的静态计算值,而移动端浏览器工具栏(地址栏、底部导航栏)显隐会导致实际可用视口高度实时变化。滚动时window.innerHeight突变,但vh不重算——结果就是元素“被撑高”或“突然上移”,视觉上明显跳变。
svh和lvh分别适合什么场景
svh(small viewport height)代表工具栏完全展开时的最小可用高度;lvh(large viewport height)代表工具栏完全收起时的最大高度。它们不是动态更新的,而是两个确定的锚点值,因此不会跳变,但需按需选用:
-
100svh:适合必须始终避开工具栏的内容,比如固定在页面底部、且绝不能被地址栏顶上去的操作按钮 -
100lvh:适合沉浸式全屏页(如启动页、广告页),希望占满设备物理屏幕最大可能区域 - 两者都不能替代
dvh做通用“当前可见高度”,但比vh更可控、无跳变
如何安全地用svh/lvh替换vh
不能全局搜索替换100vh→100svh,必须结合语义判断+降级处理:
- 优先用
@supports做特性检测,避免旧浏览器解析失败导致高度塌陷:section.fullscreen { height: 100vh; } @supports (height: 100svh) { section.fullscreen { height: 100svh; } } -
svh和lvh目前仅支持 iOS Safari 16.4+、Chrome 109+、Firefox 117+(需开启标志),Android WebView 和微信内置浏览器基本不支持 - 不要在
@media查询中使用svh/lvh——CSS 规范明确禁止在媒体查询条件里用这些单位 - JS 中无法通过
getComputedStyle读取为像素值,返回的是字符串"100svh",不能用于计算
svh/lvh的典型误用与替代思路
直接把所有100vh换成100svh会导致内容在工具栏收起后大量留白;全换100lvh又会让工具栏展开时内容被截断。真正关键的不是换单位,而是重新思考需求:
- 固定定位按钮贴底?改用
bottom: clamp(1rem, 5svh, 2rem),让距离随工具栏显隐弹性变化 - 轮播图容器需要“至少一屏高”?用
min-height: 100dvh+height: auto,内容撑开为主,dvh保底 - 弹层遮罩必须覆盖全部可视区域?
100dvh仍是首选,svh/lvh只是兜底分支,不可主用
svh和lvh的价值不在“通用替代”,而在提供两个稳定锚点——但你得先想清楚,自己要锚定的是“最小安全空间”,还是“最大沉浸空间”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











