100dvh能动态适配视觉视口高度,解决软键盘弹出、分屏等场景下100vh内容遮挡或留白问题,但需@supports检测并兼容旧版iOS Safari的JS fallback方案。
直接用 100dvh 就能解决大部分手机浏览器的全屏高度适配问题,但必须确认目标环境支持——Chrome 100+、Firefox 103+、Safari 16.4+ 才原生支持 dvh;iOS Safari 16.4 之前仍得靠 JS 补救。
iOS Safari 和部分 Android 浏览器在软键盘弹出时,100vh 仍按「布局视口」计算,而实际可视区域被压缩,导致内容被遮挡或底部留白。这不是 bug,是规范行为:vh 绑定的是 layout viewport,不是用户真正看到的 visual viewport。
height: 100vh 的登录页,键盘一弹,按钮就消失不见;固定定位的 footer 错位到屏幕中间100vh 仍按折叠态高度计算,造成大面积留白<html> 或 <body> 直接设 height: 100vh,iOS 容易触发滚动异常dvh(dynamic viewport height)是 CSS Viewport Units Level 1 标准,表示「当前视觉视口高度的 1%」,能响应键盘弹出、地址栏收起、分屏等动态变化。
@supports 包裹,否则旧浏览器会忽略整条规则:@supports (height: 100dvh) {.full-screen {height: 100dvh;}}
height: 100vh + min-height: 100dvh,避免旧版完全失效<main>),而不是全局根元素必须用 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();
height: calc(var(--vh, 1vh) * 100)
min-height: 100% 和父级 height: 100%,否则 calc() 在某些安卓 WebView 里不生效想让一个卡片在 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 防抖——这三个点踩中任意一个,全屏页面就会在真实用户手里崩一次。