首选100dvh因能自动响应视口变化且无需js,但必须用@supports(min-height:100dvh)包裹整条规则以防ios15及旧版webview失效;min-height优于height避免裁剪;绝对定位需用top/bottom替代height。

直接用 100dvh,但必须加 @supports 降级,否则 iOS 15 及更早系统会完全忽略,页面塌成一条线。
为什么 100dvh 是首选,但不能裸写
100dvh 表示“当前可见视口高度”,地址栏收起、键盘弹出、横屏切换时自动响应,无需 JS。iOS 16.4+、Chrome 105+、Edge 110+ 均已原生支持。
- 裸写
height: 100dvh:Firefox 不支持;iOS 15.x 及旧版 WebView 直接跳过该声明,元素高度回退到auto,视觉上消失或塌陷 - 必须用
@supports (min-height: 100dvh)包裹整条规则,不能只包值 —— 错写成min-height: 100vh; min-height: 100dvh;会导致新 Safari 仍用100vh,没触发 dvh - 优先用
min-height而非height:避免内容超长时被强制裁剪,用户滑不到底部
正确写法:
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
.page {
min-height: 100vh;
}
@supports (min-height: 100dvh) {
.page {
min-height: 100dvh;
}
}
-webkit-fill-available 适合简单场景,但有兼容陷阱
这是 Safari 专属的“填满可用空间”值,PostCSS 插件(如 postcss-100vh-fix)靠它实现无 JS 修复。
- 仅对
height有效,min-height不认它 - 必须配合
@supports (-webkit-touch-callout: none)检测 Safari,否则 Chrome 等浏览器会误用,导致布局异常 - 不响应键盘弹起:软键盘顶起页面时,
-webkit-fill-available不会收缩,可能遮挡输入框 - 绝对定位元素若父容器无明确高度,它也会失效 —— 它依赖包含块,不是“强制占满屏幕”
JS 动态设 --vh 是兜底方案,但防抖和时机不能错
当需兼容 iOS 15 及以下,或遇到 dvh 不稳定 WebView 时,用 JS 绑定 window.innerHeight 是最稳路径。
- 必须在
DOMContentLoaded后立即执行一次,否则首屏渲染用的是错误初始值(比如地址栏未收起时的 height) - 监听
resize即可,orientationchange在部分 iOS 版本中不可靠;地址栏显隐、键盘弹起都会触发resize - 必须防抖:iOS 连续触发
resize,直接更新样式会导致重排抖动;用requestAnimationFrame最稳妥 - CSS 中写
height: calc(var(--vh, 1vh) * 100),其中1vh是兜底,避免 JS 未加载时整个元素缩成一条线 - 别忘了给
html和body设margin: 0和height: 100%,否则window.innerHeight可能被外边距干扰
绝对定位元素最容易被忽略的坑
如果元素是 position: absolute,且父容器没设高度,100dvh 和 -webkit-fill-available 都会失效 —— 它们依赖包含块高度,不是“强制占满屏幕”。
- 改用
top: 0; bottom: 0;替代height: 100dvh,更可靠 - 若必须用
height,确保父容器有明确高度(比如height: 100%),且其祖先链上html和body已设height: 100% -
visualViewport.height更精准,但 iOS 15.0–15.3 不支持,刚加载时可能为null,需加判断,多数场景window.innerHeight已足够










