应使用100dvh替代100vh解决ios safari可视区域动态变化导致的高度错位,需前置声明100vh兜底,并用@supports(min-height: 100dvh)优雅降级;兼容旧版需js监听resize动态设置--vh变量。

移动端用 100vh 做全屏高度,大概率会出错——不是你 CSS 写错了,而是浏览器根本没按你“看到的”区域算高度。
为什么 100vh 在 iOS Safari 里不等于当前可视高度
iOS Safari 加载页面时就锁定了 vh 的计算基准:它基于「初始布局视口」(layout viewport),也就是地址栏还开着时的高度。哪怕用户一滚动地址栏就收起、可视区域变高,100vh 的值也不会更新。
- 典型现象:
height: 100vh的轮播容器,下拉后顶部被截、底部留白;overflow: hidden失效,还能向上滑出背景色 - 数值偏差在 iPhone 上常达 80–120px,不是小数点级误差,是真实错位
- Android Chrome 同样存在该问题,尤其在地址栏自动隐藏/展开时
直接换 100dvh 就行?得看浏览器和写法
100dvh 是标准解法,代表“当前动态可视区域高度”,iOS Safari 16.4+、Chrome 109+、Firefox 117+ 已稳定支持。但它不能裸用。
- 必须前置声明
100vh作为降级:height: 100vh;放在@supports外面,否则旧版 Safari 会直接忽略整条规则,导致高度塌陷 - 推荐用
min-height而非height:min-height: 100vh;→@supports (min-height: 100dvh) { min-height: 100dvh; },避免内容超长时被截断 - 别混用
dvh和svh:比如height: 100dvh+bottom: 5svh,不同设备对地址栏状态的判定逻辑不一致,fixed 元素容易错位
兼容 iOS 15 及更早版本:用 JS 动态同步 --vh
当目标环境包含大量 iOS 15.x 用户(如企业内网 WebView 或老机型存量高),纯 CSS 方案不可靠,必须 JS 回退。
- 监听
resize即可,iOS 地址栏显隐会触发该事件;不用监听scroll(高频且无必要) - 初始设置必须在 DOM ready 后立即执行,否则首屏渲染仍用错误
vh - CSS 中写成:
height: calc(var(--vh, 1vh) * 100);,其中1vh是兜底值,确保 JS 未执行时至少有基础比例参考 - 注意:SSR 渲染时服务端无法获取
window.innerHeight,首屏可能闪动,需配合hydration阶段重设
真正容易被忽略的点:绝对定位 + vh 类单位失效
如果元素是 position: absolute,而它的父容器没有显式高度(比如没设 height: 100%),那么 100vh 或 100dvh 虽然语法合法,但布局行为已脱离预期——因为绝对定位元素的百分比高度依赖包含块高度,而非视口。
- 简单绕过方式:
top: 0; bottom: 0;直接撑满,不依赖高度计算 - 若必须用高度,确保最近的相对定位祖先有
height: 100%,且其父链中html和body明确设了height: 100% - 同时要留意
env(safe-area-inset-bottom):它只对 padding/margin/height 生效,对 fixed 元素的位置微调有用,但不能用来“撑高”容器
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











