100vh在移动端不随视口变化动态更新,导致裁切、留白、错位;min-h-screen同理失效,需用@supports(min-height:100dvh)兜底并确保父容器高度链完整。

移动端 100vh 不是“失效”,而是它始终按页面加载时带地址栏的静态视口高度计算,不随滚动收起地址栏、键盘弹出或横竖屏切换动态更新——结果就是内容被裁切、底部留白、fixed 元素错位。iOS 15.x 及微信 X5 内核尤其典型,100vh 值锁死在约 844px(iPhone 14),而真实可视高度可能只有 760px。
为什么 min-h-screen 在 Tailwind 中会塌成一条线
min-h-screen 编译为 min-height: 100vh,问题根源和裸写 100vh 完全一致:iOS Safari 和微信 X5 WebView 不会重算该值。更隐蔽的是 SSR 场景下,服务端无 window 对象,min-h-screen 可能直接编译为空,首屏渲染无高度。
- 必须同时检查
html和body是否被框架或 Normalize.css 重置了height,否则百分比链路从根就断 - 哪怕用了
min-h-screen flex-1,若父容器没flex flex-col,flex-1就没空间可分 - Tailwind v3.3+ 默认支持 arbitrary value,可直接写
min-h-[100dvh],但需确认构建工具未启用postcss-100vh-fix类插件(它们会把dvh错误降级为vh)
@supports 必须包裹整条规则,不能只包值
错误写法:.page { min-height: 100vh; min-height: 100dvh; } → 老 Safari 忽略第二行,新 Safari 仍走第一行;正确写法是兜底在外、增强在内:
.page { min-height: 100vh; }
@supports (min-height: 100dvh) {
.page { min-height: 100dvh; }
}
- 兜底声明
min-height: 100vh必须写在@supports外面,确保 iOS 15.x 等环境至少有基础高度 - 不能只对属性值用
@supports,比如@supports (min-height: 100dvh) { min-height: 100dvh; }是无效语法 - 优先用
min-height,不用height:避免内容超长时被强制截断
position: absolute 或 fixed 元素设了 100dvh 没反应
百分比高度(含 100dvh)依赖包含块(containing block)的高度,不是“强制占满屏幕”。常见于弹窗、遮罩层、底部按钮等场景。
立即学习“前端免费学习笔记(深入)”;
- 父容器(如
body或直接祖先)没设min-height: 100dvh或显式高度 → 子元素的100dvh实际计算为0 - 别对
position: absolute/fixed元素用height: 100dvh,改用top-0 bottom-0更可靠(它不依赖父容器高度) - 侧边栏用
fixed时,必须加inset-y-0 left-0,而不是仅inset-0(后者在部分安卓 WebView 中行为异常)
真正容易被忽略的,是没打开开发者工具逐层点开看 Computed 面板里每一层的 height 值——只要任一层是 auto,整个百分比链路就归零。而 100dvh 的兼容性边界非常清晰:iOS 16.4+、Chrome 109+、Firefox 117+ 支持,其余环境必须 JS 回退,且首次执行必须在 DOMContentLoaded 同步完成,否则首屏就错了。


















