100dvh是当前最可靠、零js的视口高度解决方案,它基于visual viewport动态响应地址栏显隐,chrome 105+、safari 16.4+、firefox 112+已稳定支持,需搭配@supports检测并优先使用min-height而非height。

直接用 100dvh 替代 100vh,配合 @supports 降级,是当前最可靠、零 JS 的解法。
为什么 100dvh 能真正解决问题
它不是“修修补补”,而是浏览器原生支持的动态单位:值始终等于用户此刻实际看到的视口高度,地址栏收起/展开时自动更新,不依赖 JS 监听或重排计算。Chrome 105+、Safari 16.4+、Firefox 112+ 均已稳定支持,覆盖 2023 年后绝大多数活跃设备。
和 100vh 的关键区别在于语义:vh 基于 layout viewport(含地址栏),dvh 基于 visual viewport(仅当前可见区域)。
-
100vh在 iOS Safari 初始加载时可能按 812px(iPhone 13 全高)算,但用户只看到约 762px 区域,导致底部白边 -
100dvh初始就是 762px,滚动后地址栏收起,自动变为约 812px,无跳变 - 它不能用于
@media查询条件(如@media (min-height: 100dvh)无效),这点和vh一致
min-height: 100dvh 比 height: 100dvh 更安全
用 height 会强制截断内容;而 min-height 既能撑满视口,又允许内容自然溢出,更符合实际布局需求。
必须搭配 @supports 检测,否则老浏览器(如 iOS 15 或旧版 Samsung Internet)会直接忽略该声明,元素塌陷为 auto 高度。
.full-screen {
min-height: 100vh;
@supports (min-height: 100dvh) {
min-height: 100dvh;
}
}
- 不要写成
height: 100dvh—— 容易在内容超长时被裁剪 - 不要只写
min-height: 100dvh—— iOS 15 及更早版本会完全失效 - 避免在
:root或全局变量里提前定义--vh,dvh是原生单位,无需 JS 注入
别再用 -webkit-fill-available 了
它不是 100vh 的替代方案,而是历史遗留的表单控件内部填充逻辑,对 height 属性支持极差:
- iOS Safari 中行为不稳定,部分版本退化为
auto或触发意外重排 - 完全不响应地址栏显隐变化,和
100vh一样“冻结”在初始值 - Chrome / Android WebView 根本不识别
height: -webkit-fill-available,直接忽略 - 它从未被写入 CSS 规范,也不在任何现代浏览器的正式支持列表中
兼容老系统仍需 JS 降级时的关键细节
如果项目必须支持 iOS 15 或更低版本,JS 方案仍是兜底选择,但要注意三个容易被忽略的点:
- 监听
resize不够 —— 必须同时监听orientationchange,横竖屏切换也会改变window.innerHeight - 不要在
DOMContentLoaded里只取一次innerHeight—— 初始值可能仍是地址栏未收起状态下的错误值 - 用
requestAnimationFrame批量更新--vh变量,避免高频 resize 触发样式重算抖动 - 示例核心逻辑:
document.documentElement.style.setProperty('--vh', `${window.innerHeight * 0.01}px`);
真正麻烦的从来不是“怎么写”,而是“什么时候写、写几次、写完要不要再校正”。100dvh 把这些全交给了浏览器,只要记得加 @supports 和用 min-height,就基本不会翻车。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











