chrome移动端100vh跳动的本质原因是浏览器将地址栏高度计入初始window.innerheight,但工具栏收起后100vh不更新,导致滚动后视口变高而元素仍按旧高度撑开,视觉上“突然上移”。

Chrome 移动端 100vh 跳动的本质原因
不是 Chrome 有 bug,而是它把地址栏高度算进初始 window.innerHeight,但后续工具栏收起时 100vh 不更新——结果就是:滚动后视口变高,元素却还按旧高度撑开,视觉上“突然上移”。iOS Safari 同理,但 Chrome(尤其 iPad 版)更常因计算偏差导致多出滚动条。
优先用 100dvh,但必须写对顺序和用途
直接替换 height: 100vh 为 height: 100dvh 是错的。Chrome 105+、Safari 16.4+ 支持 dvh,但它返回的是字符串 "100dvh",不能用于 JS 计算,也不能在 @media 中用。
-
min-height: 100vh;是基础兜底,防止不支持dvh的环境塌陷 -
@supports (min-height: 100dvh) { min-height: 100dvh; }必须单独写,不能和height混用 - 永远别写
height: 100dvh—— 它会强制截断内容,用户滑不到底部 - PostCSS 等构建工具若自动降级
dvh为vh,必须关掉该插件功能
Chrome iOS/iPad 特别容易出问题的场景
iPad Chrome 对 100vh 的解析偏差最大,有时算出的高度接近 200vh,直接触发滚动条。这不是代码写错,是浏览器自身行为。
- 删掉所有
-webkit-fill-available,它和100vh在 iPad Chrome 中叠加会放大误差 - 显式设置
html { height: 100%; }和body { margin: 0; height: 100%; },切断继承断裂 - 若必须用
vh(比如 Canvas 渲染),改用height: calc(100vh - env(safe-area-inset-bottom))手动减去底部安全区
不支持 dvh 时,JS 监听必须用 visualViewport?.resize
微信 X5 内核、iOS 15.x、部分安卓 WebView 根本不识别 dvh,此时 JS 是唯一可靠路径。但监听 resize 在 iOS 上几乎无效——地址栏收起时不触发。
- 首选监听
visualViewport?.resize,它是目前最准的信号源 - 降级方案:
scroll+resize+orientationchange组合监听,但需节流(100–200ms) - 首次执行必须在
DOMContentLoaded前或刚进入脚本就运行,否则首屏白屏期高度就错 - CSS 中统一用
min-height: calc(var(--vh, 1px) * 100);,不要依赖父级height: 100%
真正麻烦的不是单位换不换,而是你是否真需要“绝对占满当前视口”——轮播图用 min-height: 100dvh,固定按钮用 clamp() 或 env(),弹层遮罩才值得上 JS 动态设变量。别让一个单位拖垮整套布局逻辑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











