应使用 100dvh 替代 100vh 解决 iOS Safari 中可视区域变化导致的高度错位问题,需配合 viewport-fit=cover 的 meta 标签并前置声明 100vh 作为兼容兜底。

100vh 在 iOS Safari 中实际高度 ≠ 可视窗口高度
移动端浏览器(尤其是 iOS Safari)的 100vh 是按「初始布局视口高度」计算的,不是用户当前滚动时看到的可视区域。地址栏收起/弹出时,浏览器会调整可视区域,但 100vh 值不会重算——导致内容被截断或底部留白,甚至触发意外的垂直滚动条。
典型现象:height: 100vh 的全屏轮播容器在页面下拉后顶部被遮挡,或底部出现空白;overflow: hidden 失效,仍可向上滑动看到背景色。
用 dvh 替代 100vh 解决动态适配问题
dvh(dynamic viewport height)是 CSS 新增的相对单位,代表「当前可视区域高度」,随地址栏显隐实时响应。它在 Chrome 105+、Safari 16.4+、Firefox 112+ 已稳定支持。
- 直接替换:把
height: 100vh改成height: 100dvh - 注意兼容性兜底:旧版 Safari 不识别
dvh,会回退到前一条声明(需前置100vh) - 示例写法:
section.fullscreen {<br> height: 100vh;<br> height: 100dvh;<br>}
需要兼容老 iOS Safari?用 svh 或 JS 动态修正
svh(small viewport height)代表「最小可能可视高度」,即地址栏完全展开时的高度。它比 dvh 更保守,在 Safari 16.2+ 支持,但对「地址栏收起后想撑满」的场景不够灵活。
立即学习“前端免费学习笔记(深入)”;
若必须支持 iOS 15.x 或更早版本:
- 避免依赖纯 CSS 方案,改用 JS 获取
window.innerHeight并写入 CSS 变量 - 监听
resize和scroll(iOS 上 scroll 触发时机特殊,建议加防抖) - 示例:
document.documentElement.style.setProperty('--vh', `${window.innerHeight * 0.01}px`);<br>// 然后在 CSS 中用 height: calc(100 * var(--vh));
别忽略 viewport meta 标签的影响
即使用了 100dvh,如果页面 <meta name="viewport" content="..."> 缺失或设置了 user-scalable=no,某些 Android 浏览器仍可能冻结视口尺寸,导致 dvh 不更新。
- 确保包含:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> -
viewport-fit=cover是关键,它允许内容延伸至刘海/圆角区域,并配合dvh正确计算安全区外高度 - 移除
user-scalable=no—— 它会干扰浏览器对可视区域变化的感知
真实项目里最常漏掉的是 viewport-fit=cover 和 dvh 的声明顺序。前者不加,dvh 在部分机型上形同虚设;后者没前置 100vh,老浏览器直接失效且无报错。


















