100dvh是解决ios safari中100vh因布局视口与视觉视口不一致导致高度计算错误的现代方案,需搭配min-height:100vh和@supports检测,并为ios15/微信webview等旧环境提供节流resize的js兜底。

直接用 100dvh 替代 100vh,但必须搭配 min-height: 100vh 和 @supports 检测,否则 iOS 15、微信 WebView 等环境会完全塌陷。
为什么 100vh 在 iOS Safari 里“多算”了工具栏
100vh 基于「布局视口(layout viewport)」计算,把地址栏、底部导航栏这些可隐藏区域全包进去了;而用户滚动时看到的是「视觉视口(visual viewport)」,二者不一致。结果就是:
- 页面刚加载:地址栏展开 →
100vh偏高 → 底部大片留白 - 用户一滚动:地址栏收起 → 实际可视区变大,但
100vh的像素值冻结不动 → 内容被截、flex居中失效、calc(100vh - 60px)计算失准
100dvh 是唯一语义正确的现代解法
100dvh(dynamic viewport height)代表“此刻用户真正看到的高度”,浏览器原生响应工具栏显隐,iOS 16.4+、Chrome 109+、Firefox 117+ 已稳定支持。但要注意:
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
- 必须用
min-height,不是height:避免内容超长时被裁剪 -
min-height: 100vh必须写在@supports外层:否则老设备直接忽略整条规则 - 别写成
height: 100vh; height: 100dvh;:Safari 会取后者,但没@supports包裹时旧版直接丢高度 -
100dvh不能用于@media查询(如@media (min-height: 100dvh)是非法语法)
兼容 iOS 15 及微信 WebView 的兜底必须用 JS
微信内置浏览器、QQ 浏览器、iOS 15.x 等环境根本不认 dvh 或 svh,CSS 方案在此类场景下完全失效。此时唯一可靠路径是监听 resize(不是 scroll),动态设置 CSS 变量:
- 首次执行必须在
DOMContentLoaded前或同步运行,否则首屏白屏期高度就错 -
resize在 iOS 上滚动时高频触发,直接赋值style.height会导致强制同步布局卡顿;务必用节流(建议 100–200ms)包裹更新逻辑 - 只更新真正需要适配的元素,比如加了
data-dynamic-height的容器,避免全局重排 - CSS 中写
height: calc(var(--vh, 1px) * 100),别漏单位(1px而非1vh),否则 fallback 会失效
彻底弃用 -webkit-fill-available
-webkit-fill-available 不是解药:
- 它是 WebKit 早期为
<input>等表单控件设计的内部填充逻辑,不适用于通用容器高度 - iOS Safari 对
height: -webkit-fill-available支持极不稳定,部分版本退化为auto或触发意外重排 - 它无法响应地址栏收起/展开,和
100vh一样“冻结”在初始值 - Chrome / Android WebView 完全不识别该值用于
height,声明直接被忽略
复杂点在于:不同机型、不同 WebView 版本对新单位的支持断层明显,而 JS 动态方案又容易因节流不当引发卡顿——最稳妥的做法是先上 100dvh + @supports,再按 UA 或特性检测决定是否注入 resize 脚本。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










