100dvh能动态适配视觉视口高度,解决软键盘弹出、分屏等场景下100vh内容遮挡或留白问题,但需@supports检测并兼容旧版iOS Safari的JS fallback方案。

直接用 100dvh 就能解决大部分手机浏览器的全屏高度适配问题,但必须确认目标环境支持——Chrome 100+、Firefox 103+、Safari 16.4+ 才原生支持 dvh;iOS Safari 16.4 之前仍得靠 JS 补救。
为什么不能继续用 100vh 做全屏高度
iOS Safari 和部分 Android 浏览器在软键盘弹出时,100vh 仍按「布局视口」计算,而实际可视区域被压缩,导致内容被遮挡或底部留白。这不是 bug,是规范行为:vh 绑定的是 layout viewport,不是用户真正看到的 visual viewport。
- 常见错误现象:
height: 100vh的登录页,键盘一弹,按钮就消失不见;固定定位的 footer 错位到屏幕中间 - Android 分屏/折叠屏下更糟:某些三星折叠屏展开后,
100vh仍按折叠态高度计算,造成大面积留白 - 不要给
<html>或<body>直接设height: 100vh,iOS 容易触发滚动异常
100dvh 是什么,怎么安全使用
dvh(dynamic viewport height)是 CSS Viewport Units Level 1 标准,表示「当前视觉视口高度的 1%」,能响应键盘弹出、地址栏收起、分屏等动态变化。
- 必须用
@supports包裹,否则旧浏览器会忽略整条规则:@supports (height: 100dvh) { .full-screen { height: 100dvh; } } - 降级 fallback 推荐写成:
height: 100vh+min-height: 100dvh,避免旧版完全失效 - 优先作用于 wrapper 元素(如
<main>),而不是全局根元素
旧版 iOS Safari(
必须用 JS 动态监听并更新自定义 CSS 变量,且要防抖——Safari 的 resize 在键盘收起时可能连续触发 3–5 次。
立即学习“前端免费学习笔记(深入)”;
- 核心代码:
const updateVh = () => { document.documentElement.style.setProperty('--vh', `${window.innerHeight * 0.01}px`); }; let resizeTimer; window.addEventListener('resize', () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(updateVh, 50); }); updateVh(); - CSS 中配合使用:
height: calc(var(--vh, 1vh) * 100) - 别忘了同时设
min-height: 100%和父级height: 100%,否则calc()在某些安卓 WebView 里不生效
混用 vw 和 vh 会导致比例失真
想让一个卡片在 iPhone 和 iPad 上都保持正方形?width: 50vw; height: 50vh 不行——因为不同设备宽高比差异太大,计算结果根本不是 1:1。
- 正确做法:改用
vmin,比如width: 50vmin; height: 50vmin;,它取vw和vh中较小值,天然保方 - 图标、头像容器、按钮尺寸这类需固定比例的场景,一律优先
vmin/vmax,而非混用vw/vh - 背景图、字体大小、横向滚动项这些单向依赖的场景,
vw或vh单独用很安全
真正麻烦的从来不是写对那行 100dvh,而是忘记检查 Safari 版本、没加 @supports、或者在旧 iOS 上漏掉 resize 防抖——这三个点踩中任意一个,全屏页面就会在真实用户手里崩一次。


















