应使用100dvh替代100vh解决ios safari可视区域动态变化导致的高度错位,需前置声明100vh兜底、添加viewport-fit=cover的meta标签,且height: 100vh必须写在height: 100dvh之前以确保旧版safari正常回退。

直接用 100dvh 替换 100vh,再加 viewport-fit=cover 的 <meta> 标签,就能解决 90% 的 iOS Safari 地址栏遮挡和滚动条异常问题。 不是所有浏览器都支持 dvh,但当前(2026 年中)主流环境已覆盖充分——关键在声明顺序和兜底逻辑,而不是写一堆 JS。
为什么 100vh 在移动端会出错
它不是“当前能看到的高度”,而是页面加载那一刻的设备视口高度(含地址栏)。iOS Safari 地址栏收起时,可视区域变高,但 100vh 值不变,导致容器实际比屏幕高——要么底部被截断,要么触发意外滚动条。典型表现:height: 100vh 的登录框,一滚动就看不见按钮;overflow: hidden 失效,还能往上滑出背景色。
用 100dvh 替换必须注意三件事
– 必须把 height: 100vh 写在前面,height: 100dvh 写在后面,否则旧版 Safari 会直接忽略整条规则
– <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> 要存在且不能带 user-scalable=no,否则 dvh 不更新
– 不要用 @supports 包裹整个样式块,只对需要动态适配的元素加,比如全屏轮播、登录页容器:
.fullscreen {
height: 100vh;
height: 100dvh;
}
兼容 iOS 15.x 或更老版本?别硬扛,降级要干净
JS 动态方案不是“获取一次 window.innerHeight”就行,重点在响应变化:
– iOS 地址栏显隐不触发 resize,必须监听 scroll 和 orientationchange
– 直接设 document.documentElement.style.setProperty('--vh', ...),CSS 里用 calc(var(--vh, 1vh) * 100)
– 加 requestAnimationFrame 节流,否则滚动卡顿
– 初始值要在 DOM ready 后立刻设置,否则首屏仍错位
真正容易被忽略的,是 viewport-fit=cover 和声明顺序——很多项目写了 100dvh 却没生效,翻来覆去查 JS,结果只是 meta 标签漏了或顺序反了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











