css变量本身不解决vh适配问题,它只是传递js计算出的实时视口高度的管道;真正起作用的是window.innerheight,而变量只是让css能“读到”这个值。

直接说结论:CSS变量本身不解决vh适配问题,它只是传递JS计算出的实时视口高度的管道;真正起作用的是window.innerHeight,而变量只是让CSS能“读到”这个值。
为什么不能只靠--vh变量初始化一次
移动端地址栏收起/展开、软键盘弹出、横竖屏切换都会改变window.innerHeight,但CSS变量不会自动更新。只在页面加载时设一次--vh,后续所有布局就基于那个过期数值——比如横屏切回竖屏后,--vh还是旧的宽高比对应值,导致元素被拉伸或截断。
- 必须监听
resize事件(iOS对orientationchange支持不稳定,resize更可靠) - 某些iOS版本地址栏收起时不触发
resize,需额外监听scroll(但要节流,避免卡顿) - 首次渲染前就要执行设置逻辑,否则白屏阶段用的是
1vh兜底,可能极短时间闪动
--vh变量的正确写法和fallback陷阱
变量值不是像素数,而是px单位的1%基准,所以得乘以100。同时必须设初始值,否则calc(var(--vh, 1vh) * 100)里的1vh会失效——因为1vh是相对单位,不能直接参与calc中的数值运算,应写作1px或明确单位。
- JS中应写:
document.documentElement.style.setProperty('--vh', `${window.innerHeight * 0.01}px`) - CSS中对应写:
height: calc(100 * var(--vh, 1px)),而非calc(var(--vh, 1vh) * 100) - 千万别漏
@supports (color: oklch(0 0 0))这类无意义检测——真正要检测的是@supports (height: 100dvh),有则优先用dvh,没则走变量逻辑
和100dvh比,变量方案复杂在哪
100dvh是浏览器原生支持的动态单位,iOS 16.4+、Chrome 100+已稳定可用,它自动响应地址栏、键盘、安全区变化。而JS+CSS变量方案本质是手动模拟这个行为,但模拟不全:
- WebView环境(如微信内置浏览器、部分安卓定制壳)可能不触发
resize,得加setInterval轮询innerHeight,但耗性能 -
env(safe-area-inset-bottom)必须单独处理,dvh已包含该修正,变量方案得额外叠加计算 - 滚动过程中高频更新
--vh会导致重排,requestAnimationFrame节流是硬性要求,否则iOS上明显卡顿
真正难的不是写几行JS,而是覆盖所有边界场景:横竖屏切换瞬间的抖动、键盘弹出时的布局冻结、WebView里事件缺失、老iOS机型的兼容降级路径。这些细节堆起来,才决定用户看到的是“刚好填满”,还是“忽长忽短”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











