必须用 @supports (min-height: 100dvh) 包裹整条规则,否则 ios 15 及更早系统会忽略 100dvh 导致元素高度回退为 auto;因 safari 视口定义固定,100vh 不随地址栏收起或键盘弹出更新,易造成截断或空白;100dvh 需搭配 min-height 使用并注意父容器高度上下文,js 动态设 --vh 是最稳兜底方案。

直接用 100dvh,但必须用 @supports (min-height: 100dvh) 包裹整条规则,否则 iOS 15 及更早系统会完全忽略该声明,元素高度回退到 auto,页面视觉上塌陷或消失。
为什么 100vh 在 iOS Safari 里会溢出或留白
它不是 bug,而是 Safari 对「视口」的定义不同:100vh 按页面加载时的初始布局视口(含地址栏)计算,之后滚动、地址栏收起、键盘弹出都不会更新这个值。结果就是——地址栏收起后可视区域变高了,但 100vh 还卡在旧高度,要么内容被截断,要么底部多出空白甚至触发意外滚动条。
典型现象包括:overflow: hidden 失效、position: fixed 元素错位、全屏轮播图顶部被遮挡、底部按钮上浮。
用 100dvh 替代前必须加 @supports 降级
裸写 min-height: 100dvh 或 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;
}
}
绝对定位元素最容易被忽略的坑
如果你给一个 position: absolute 元素设了 height: 100dvh,但它的父容器没有明确高度(比如只是 position: relative 且无 height),那它依然会失效 —— dvh 单位本身没问题,但它依赖包含块的计算上下文。
- 绝对定位元素若父容器无显式高度,
100dvh不会自动“撑满屏幕”,而是按最近有高度的祖先计算 - 此时更稳妥的做法是用
top: 0; bottom: 0;替代height: 100dvh,只要父容器是position: relative或fixed - 别忘了同时检查
html和body是否有默认margin,它们会影响window.innerHeight的取值,进而干扰 JS 方案
当 100dvh 不可用时,JS 动态设 --vh 是最稳兜底
遇到 iOS 15 及以下、或某些 WebView 中 dvh 行为不稳定时,JS 是唯一能精确响应每次视口变化的路径。
- 必须在
DOMContentLoaded后立即执行一次,否则首屏渲染用的是错误初始值(比如地址栏未收起时的innerHeight) - 监听
resize即可,orientationchange在部分 iOS 版本中不可靠;地址栏显隐、键盘弹起都会触发resize - 必须防抖:iOS 连续触发
resize,直接更新样式会导致重排抖动;用requestAnimationFrame最稳妥 - CSS 中写
height: calc(var(--vh, 1vh) * 100),其中1vh是兜底,避免 JS 未加载时整个元素缩成一条线
真正难处理的从来不是“怎么写”,而是「哪些场景下 dvh 会静默失效」——比如嵌套在 Webview 里的 H5、某些 PWA 模式、或 iPadOS 上的 Chrome for iOS。这些地方往往连 @supports 都检测不到问题,只能靠真机 + 视觉回归验证。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











