根本原因是safari将100vh绑定到静态布局视口而非动态视觉视口,导致地址栏收起、键盘弹出等场景下高度不重算;应使用@supports包裹的min-height: 100dvh替代,并确保父容器有高度或改用top: 0; bottom: 0;。

100vh在Safari中跳动的根本原因
不是代码写错,是 Safari 把 100vh 绑定到「布局视口」而非「视觉视口」——页面加载瞬间就冻结了值,后续地址栏收起、键盘弹出、横竖屏切换都不会触发重算。比如 iPhone 14 的物理屏高是 844px,1vh 就被固定为 8.44px,哪怕滚动后实际可视高度变成 762px,100vh 还是死守 844px,导致元素撑高、底部露白、position: fixed 错位。
为什么用min-height: 100dvh比height: 100dvh更安全
100dvh 确实能响应可视区域变化,但直接写 height: 100dvh 有硬伤:
- 内容超长时会被强制裁剪,用户滑不到底部
- iOS 15 及更早版本完全忽略该声明,元素高度回退为
auto,整块塌陷 -
@supports必须包裹整个规则块,不能只包值,否则新 Safari 仍走100vh路径
正确姿势是:
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
.page {
min-height: 100vh;
}
@supports (min-height: 100dvh) {
.page {
min-height: 100dvh;
}
}
绝对定位元素为啥用了100dvh还是不占满
因为 100dvh 不是“强制撑满窗口”,它依赖包含块(containing block)的高度。如果父容器没设高度(比如只是 position: relative 且没 min-height),那 min-height: 100dvh 就无效。
- 确保父级(如
body或直接祖先)有min-height: 100dvh或显式高度 - 对
position: absolute元素,更稳的写法是top: 0; bottom: 0;,绕过高度继承链 - 别信
-webkit-fill-available:它只对height生效,min-height不认;软键盘弹起时不响应;iPad Chrome 中甚至叠加翻倍
JS读不到100dvh的真实像素值
getComputedStyle(el).height 返回的是字符串 "100dvh",不是数字,没法直接用于计算或动画。需要时得用 window.innerHeight 手动同步,但要注意:
-
window.innerHeight在地址栏收放瞬间会抖,建议配合requestAnimationFrame节流 -
@media查询不支持dvh单位,@media (min-height: 100dvh)是非法语法 - PostCSS 等构建工具若自动转换单位,必须关掉对
dvh的处理,否则可能错误降级为vh
真正难搞的不是怎么写,而是哪些地方根本不能用 dvh —— 比如要算背景图缩放比例、做 scroll-driven 动画、或依赖 CSSOM 读取像素值的场景,这时候就得回退到 env(height) 或 JS 补偿。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










