不能裸用100dvh,必须用@supports(min-height:100dvh)包裹并兜底min-height:100vh,因ios15及更早、微信webview等不支持dvh会导致声明丢弃和高度塌陷;svh/lvh/dvh语义不同,须分别检测且不可混用。

直接写 100dvh 会炸,必须加 @supports 检测
iOS 15 及更早、微信内置 WebView(截至 2026 年 5 月)、QQ 浏览器等环境根本不认识 dvh,解析失败后整条 CSS 声明被丢弃,容器高度塌陷成 auto,页面直接错位或留白。不能裸用。
正确姿势是先兜底 100vh,再用 @supports 升级:
.full-height {
min-height: 100vh;
}
@supports (min-height: 100dvh) {
.full-height {
min-height: 100dvh;
}
}
-
@supports必须精确匹配:写成(height: 100dvh)无效,因为height不支持dvh,只允许用于min-height/max-height -
@supports (dvh: 1px)是非法语法,浏览器不识别,别试 - 多个单位要分别检测:
svh和dvh语义独立,不能合在一个@supports块里写成@supports (min-height: 100dvh), (min-height: 100svh)——这是“与”关系,任一不支持就全失效
dvh、svh、lvh 完全不是替代关系,混用必错
看到 100svh 就以为是“更小的 dvh”?不对。三者基准不同,数值不可比,也不能叠加使用。
-
100svh= 地址栏**强制显示时**的最小可用高度 → 适合支付页底部按钮、弹窗确认区(确保永远不被遮挡) -
100lvh= 地址栏**强制隐藏时**的最大高度 → 适合全屏视频、Canvas 绘图(但滚动初期顶部可能被盖住) -
100dvh= 当前**实时可视区域高度** → 适合轮播图容器、固定底栏(滚动时自动响应) - 在同一个组件里同时写
height: 100dvh和padding-bottom: 10svh,结果不可预测,因为两个单位的“1%”指向完全不同的参考系
监听 scroll 更新高度?错,得监听 resize + orientationchange
iOS Safari 地址栏显隐不触发 scroll,而是触发 resize。只监听 scroll 会导致高度滞后甚至完全不更新。
- 必须监听
resize和orientationchange(横竖屏切换),否则真机上滚动时dvh值不会刷新 - 若需 JS fallback(比如微信环境),更新
--dvh自定义属性时要用requestAnimationFrame节流,避免频繁重排 - 别依赖
window.innerHeight直接赋值——某些 Android WebView 返回的是设备物理高度,不是当前可视高度
真机测试比模拟器重要,iOS 16.4+ 才原生支持 dvh
模拟器常默认启用新特性,但真实用户环境差异极大。iOS 16.4 是分水岭,旧版 Safari 完全不支持 dvh;微信 WebView 即使底层 Chromium 版本够新,WebView 层也常禁用该能力。
- Safari 16.4–17.2 存在首屏渲染时机问题:首次计算
100dvh时地址栏状态未稳定,可能短暂取到错误高度,导致闪动 - 微信环境必须 JS fallback,纯 CSS 不够用——这点最容易被忽略,尤其当产品上线后才发现大量用户卡在支付页底部按钮被盖住
-
svh和lvh的支持范围比dvh更窄,目前仅部分 Chrome Android 和 Firefox(需手动开启 flag)支持,不能当作通用降级方案
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











