100vh在ios safari中不准确是因将地址栏高度计入计算,应使用@supports(min-height:100dvh)包裹整条规则并外置min-height:100vh兜底,避免旧版safari忽略声明导致塌陷;绝对定位元素需用top:0;bottom:0;替代height:100dvh,兼容ios15及微信webview必须js动态设--vh并监听resize。

100vh 在 iPhone 上不准确,不是你写错了,是 Safari 把地址栏高度算进去了——页面刚加载时地址栏挂着,window.innerHeight 可能是 762px,但 1vh 却按设备物理屏高(比如 iPhone 14 的 844px)算成 8.44px,导致 100vh 实际为 844px,比你能看见的区域多出约 80px。
为什么 @supports (min-height: 100dvh) 必须包裹整条规则
iOS 15.x 及更早版本完全不认识 100dvh,会直接忽略整条声明;如果只写:.page { min-height: 100vh; min-height: 100dvh; }
老 Safari 忽略第二行,新 Safari 仍走第一行,问题照旧。必须让 @supports 包住整个选择器块,兜底声明写在外面:
.page { min-height: 100vh; }
@supports (min-height: 100dvh) {
.page { min-height: 100dvh; }
}
- 外层
min-height: 100vh是保底,确保老环境至少有基础高度 - 不能只包值,比如
min-height: 100dvh单独一行放在@supports里但没包选择器——CSS 解析器可能跳过整条规则 - PostCSS 插件常把
100dvh错误降级成100vh,建议禁用相关转换
绝对定位元素设了 100dvh 为啥没撑开
position: absolute 元素的百分比高度(包括 100dvh)依赖包含块(containing block)的高度,不是“强制占满屏幕”。常见于弹窗、遮罩层、底部按钮等场景:
- 父容器(如
body或某个 wrapper)没设min-height: 100dvh或显式高度 → 子元素100dvh实际计算为 0 - 别对绝对定位元素用
height: 100dvh,改用top: 0; bottom: 0;,更稳定且不依赖父容器高度 - 若父容器本身靠
--vh驱动,JS 初始化必须先于子元素渲染,否则读到的是初始1px
需要兼容 iOS 15 及微信 WebView?JS 动态设 --vh 是唯一解
这些环境根本不识别 dvh 或 svh,纯 CSS 方案会塌成一条线。必须用 JS 回退:
- 在
DOMContentLoaded后立即执行一次,否则首屏渲染用的是地址栏未收起时的错误初始值 - 监听
resize(地址栏收放、键盘弹出、横竖屏都会触发),不用监听scroll(iOS 地址栏收起时仅部分版本触发) - 防抖必须用
requestAnimationFrame,setTimeout在微信安卓下易卡死 - CSS 中统一写
min-height: calc(var(--vh, 1px) * 100),其中1px是兜底,避免 JS 未执行时完全无高度
真正容易被忽略的是:即使你用了 100dvh,也要检查父容器是否参与高度继承链;而一旦引入 JS 方案,requestAnimationFrame 防抖和首次同步执行这两个点,漏掉任何一个都会导致首屏白屏或滚动跳变。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











