最稳定解法是用 min-h-[100dvh] 配合 flex flex-col 布局,因 100dvh 是动态单位,iOS 16.4+/Chrome 109+ 已支持,可避免软键盘弹出时 vh 不更新导致的截断或留白问题。

直接换掉 h-screen 和 min-h-screen,改用 min-h-[100dvh] 并配 flex flex-col 布局——这是目前最稳定、浏览器支持度最高、且无需 JS 的解法。
为什么 h-screen 在移动端必然失效
它编译为 height: 100vh,而 vh 是静态单位:iOS Safari(尤其 16.3 及更早)在软键盘弹出后不更新视口高度值,仍按初始状态计算;华为/UC 等 WebView 甚至直接忽略该声明。结果就是内容被截断或底部留白,不是 Tailwind 写错了,是单位本身不可靠。
-
min-h-screen同样依赖100vh,只是加了min-前缀,无法解决动态变化问题 - 别指望
h-full补救:它依赖父容器高度,而父容器若没设高,就陷入循环依赖 -
100dvh才是真·动态单位,iOS 16.4+、Chrome 109+ 已稳定支持,Tailwind ≥ 3.3 可直接用
必须搭配 flex flex-col 才生效
min-h-[100dvh] 只设最小高度,不自动分配空间。若不用 Flex 布局,子元素不会弹性伸缩,flex-1 就是摆设。
- 结构必须是:
<div class="min-h-[100dvh] flex flex-col"> <header></header><main class="flex-1 overflow-y-auto"></main><footer class="flex-shrink-0"></footer> </div> -
main加flex-1(或显式flex-grow flex-shrink-0 min-w-0),防文字溢出撑宽 -
footer必须加flex-shrink-0,否则键盘弹出会把它压扁 - 删掉
html或body上的h-full/min-h-full,它们会干扰dvh行为
viewport meta 不干净,dvh 直接打滑
<meta name="viewport" content="width=device-width, initial-scale=1.0"> 必须存在且干净。任何额外参数都会降级兼容模式:
- 删掉
height=device-height—— 它会让所有vh/dvh类失效 - 删掉
maximum-scale=1和user-scalable=no—— iOS 会强制进入兼容模式,visualViewport不可用 - 真机测试时,用
document.documentElement.clientWidth对比window.screen.width:若前者明显偏小,说明 Safari 自动缩放了(常见于未设max-w-full的图片或长单词)
右侧黑边?不是 overflow-x-hidden 没加,是某个元素真·越界了
所谓“黑边”,是某个子元素宽度 > 100vw,浏览器强制渲染横向滚动区域,深色背景没覆盖过去。你加 overflow-x-hidden 无效,说明问题不在 body 层级。
- 打开 Chrome DevTools → Rendering → 勾选 Highlight overflows,红色标记处就是越界源
- 高频越界点:
ml-40/mr-32类在小屏下把元素整体右推;img未设max-w-full;flex子项用了shrink-0却没限制宽度 - 全局兜底:
+ 确保viewport正确
真正麻烦的不是换单位,而是所有依赖高度的布局都要同步改:flex 子项是否被拉伸、fixed 元素是否彻底脱离文档流、overflow 是否触发 BFC——漏掉任意一环,100dvh 也救不回来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











