<p>100dvh是首选方案,需用@supports包裹整条规则并降级至100vh;--vh变量仅为iOS 15及微信WebView等不支持环境的兜底,须监听resize、scroll等事件动态更新,且CSS中必须用calc(100 * var(--vh, 1px))配合多层fallback。</p>

直接用 100dvh 就能解决大部分场景,--vh 变量只是兜底手段,不是首选方案。 它本质是手动模拟浏览器行为,写错一行、漏一次节流、少一层 fallback,就会在微信 WebView 或 iOS 15 以下机型上出现白边、跳变甚至塌陷。
为什么不能只靠 JS 初始化一次 --vh
移动端地址栏收起、软键盘弹出、横竖屏切换都会改 window.innerHeight,但 CSS 变量不会自动更新。只在 DOMContentLoaded 里设一次 --vh,后续所有布局就基于那个过期值——比如横屏切回竖屏后,--vh 还是旧的宽高比对应值,导致元素被拉伸或底部留白。
- 必须监听
resize事件(orientationchange在 iOS 上支持不稳定) - 某些 iOS 版本地址栏收起时不触发
resize,需额外监听scroll并节流 - 首次渲染前就要执行设置逻辑,否则白屏阶段用的是
1px兜底,可能极短时间闪动
--vh 的正确赋值和 CSS fallback 写法
JS 中设变量时,值必须是带 px 单位的数值,且是 window.innerHeight * 0.01(即 1% 高度),不是直接塞 vh 单位;CSS 中用 calc() 乘以 100,且 fallback 必须是绝对单位(如 1px),不能是 1vh——因为 1vh 是相对单位,无法参与 calc 数值运算。
- JS 正确写法:
document.documentElement.style.setProperty('--vh', `${window.innerHeight * 0.01}px`) - CSS 正确写法:
height: calc(100 * var(--vh, 1px)),不是calc(var(--vh, 1vh) * 100) - 必须双层回退:
min-height: 100dvh; min-height: calc(100 * var(--vh, 1px)); min-height: 100vh;
绝对定位元素用 --vh 的常见失效点
如果你给一个 position: absolute 元素写了 min-height: calc(100 * var(--vh, 1px)),但它的父容器没设明确高度(比如只是 position: relative 且无 height),那它依然不会占满屏幕——--vh 值本身没错,但它依赖包含块的高度上下文。
立即学习“前端免费学习笔记(深入)”;
- 确保父容器(如
body或直接祖先)有min-height: 100dvh或显式高度 - 更稳妥的是用
top: 0; bottom: 0;替代height类声明 - 别信
-webkit-fill-available:它只对height有效,min-height不认;不响应软键盘弹起;iPad Chrome 中甚至会叠加导致高度翻倍
真正难处理的从来不是代码怎么写,而是哪些时机要监听、哪些机型要降级、哪些 fallback 要嵌套三层——这些细节一旦漏掉,用户一滑动页面,视口就“断层”。


















