uni-app H5端页面高度塌陷源于iOS Safari对vh的动态重算,应禁用vh适配,改用rem+动态监听resize/orientationchange并延时更新根字体大小,避免依赖window.innerHeight即时值。

uni-app H5端页面高度塌陷的典型表现
打开H5页面后,page 或 view 内容没撑开,底部留白、滚动条失效、vh 计算错乱——这不是 CSS 写错了,是移动端浏览器(尤其 iOS Safari)对 vh 的实现不一致导致的。iOS Safari 在地址栏收起/展开时会动态重算 vh,但 uni-app 默认用的是 vh 做视口基准,结果就是“高度突然缩水”。
uni-app 中禁用 vh 适配,改用 px + 动态计算
uni-app 的 vue.config.js 或 manifest.json 里默认开启 viewport 适配,它会把 750rpx 映射到 100vw,而 vw 又依赖 vh 行为,绕不开塌陷。最稳的方式是关掉它,手动接管:
- 在
manifest.json中设置"display":"standalone"(非必须,但能减少 Safari 地址栏干扰) - 在
main.js或App.vue的onLaunch中执行:const doc = document.documentElement; doc.style.fontSize = window.innerHeight / 10 + 'px'; // 把 100vh 拆成 10 份,1rem ≈ 10vh
- 所有布局单位改用
rem,比如height: 10rem≈ 满屏高;避免直接写height: 100vh
iOS Safari 下 window.innerHeight 不可靠怎么办
直接读 window.innerHeight 在 iOS Safari 页面刚加载或地址栏变化时经常滞后,比如横竖屏切换后值还是旧的。不能只靠 onload 一次赋值。
- 监听
resize和orientationchange事件,但注意 iOS Safari 的resize触发不及时 - 更稳妥的做法是加一个
setTimeout延迟重算,例如:function updateRootFontSize() { setTimeout(() => { const h = window.innerHeight || document.documentElement.clientHeight; document.documentElement.style.fontSize = h / 10 + 'px'; }, 100); } window.addEventListener('resize', updateRootFontSize); window.addEventListener('orientationchange', updateRootFontSize); - 如果用了
uni.navigateTo切页,记得在目标页面也调一次,因为部分机型切页后innerHeight未更新
为什么不用 env(safe-area-inset-bottom) 解决塌陷
env(safe-area-inset-bottom) 是为刘海屏/Home Indicator 留白设计的,和高度塌陷无关。它不会修复 vh 动态变化的问题,反而可能让底部区域被误判为“不可用”,进一步压缩可用高度。
真正要防的不是安全区,是 Safari 对 vh 的“懒更新”。所以别指望 CSS 环境变量兜底,得从 JS 层面主动同步视口真实高度。
复杂点在于:不同 iOS 版本对 resize 的触发时机差异大,有些甚至需要监听 scroll 才能感知地址栏变化。上线前务必在真机上用 Safari 的远程调试反复测横竖屏、呼出键盘、切后台再回来这些场景。


















