必须用 min-h-[100dvh] 配合 flex flex-col 才能解决移动端键盘弹出导致的塌陷问题,因 100dvh 动态响应可见视口高度变化,而 100vh 在 ios safari 等环境中不更新;老环境需 js 动态注入 --vh 变量兜底。

直接用 min-h-[100dvh] 替代 min-h-screen 或 h-screen,但必须配 flex flex-col 布局,否则它只设最小高度,不触发子项伸缩 —— 这是绝大多数人写完 dvh 还塌陷的根本原因。
为什么 100dvh 能解决键盘弹出时的塌陷
移动端软键盘弹出会大幅压缩可视区域,而 100vh 在 iOS Safari 中完全不更新、在部分安卓 WebView 中甚至被忽略;100dvh 则代表“当前可见视口高度”,浏览器内核会在键盘弹起/收起瞬间同步更新该值。这意味着容器高度能真实跟随用户当前可操作区域变化,不会出现“容器还撑着原来的高度,内容却被顶到屏幕外”的错位。
常见错误现象:
-
min-h-screen在键盘弹出后底部留白或按钮消失 - 使用
height: 100vh的登录页,输入框聚焦后整个页面向上偏移、CTA 按钮被遮住
注意:不是所有“看起来像全屏”的场景都适合 dvh —— 比如你希望首屏固定为“地址栏收起状态下的最大高度”,反而该用 100lvh(least viewport height)。
min-h-[100dvh] 必须配合 flex flex-col 才生效
Tailwind 的 min-h-[100dvh] 只设置最小高度,不控制内部子元素如何分配剩余空间。若没加 flex flex-col,主内容区即使写了 flex-1 也不会拉伸,导致视觉上还是塌成一条线。
正确结构要点:
- 根容器加
flex flex-col min-h-[100dvh] - 主内容区加
flex-1(等价于flex: 1 1 0%),推荐显式写flex-grow flex-shrink-0 min-w-0防止文字溢出撑宽 - 底部固定区域(如提交按钮)必须加
flex-shrink-0,否则键盘弹出时会被 flex 压缩变形 - 不要给
html或body设h-full或min-h-full,这会干扰 dvh 的计算逻辑
微信、iOS 15.x 等老环境兜底必须用 JS
dvh 在微信内置浏览器(X5 内核)、iOS 15.x 及更早版本、部分安卓 WebView 中完全不识别,CSS 规则直接被忽略。此时仅靠 height: 100vh; height: 100dvh 的层叠写法无效 —— 浏览器连 100dvh 都不解析,自然不会 fallback 到前一条。
可靠兜底方案只有 JS 动态注入 CSS 变量:
- 监听
resize和scroll(尤其要防抖 +requestAnimationFrame) - 必要时监听微信 JSBridge 的网络类型回调(
WeixinJSBridge.invoke('getNetworkType', ...))来触发重算 - 用
window.innerHeight计算实时视口高度,写入:root的--vh变量 - CSS 中用
height: calc(var(--vh, 1vh) * 100),其中1vh是保底单位
别漏掉安全区:即使高度算准了,微信 iOS 底部「小白条」、Android 全面屏手势区仍需用 padding-bottom: env(safe-area-inset-bottom) 预留空间。
真正难的从来不是换一个单位,而是理解 dvh 不是“100vh 的升级版”,而是“另一个问题的答案”——它只在你需要响应“此刻可见区域”时才成立;一旦涉及滚动锚点、动画帧同步、或需要兼容 X5 内核,就得立刻切回 JS 控制,且 resize 监听不能只靠窗口尺寸变化,得把 scroll、focus、input 弹起这些信号都串起来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











