ios safari中100vh“短一截”是因地址栏高度被计入但不随收放更新,应改用min-h-[100dvh]并配合flex布局与flex-1等逻辑,老版本需js动态设置--vh变量兜底。

为什么100vh在iOS Safari里“短一截”
不是你的Tailwind类写错了,是iOS Safari把地址栏高度算进100vh,但用户滑走地址栏后,100vh值不更新——导致实际可视区域变大,而元素高度卡死在旧值上,底部必然留白。Android Chrome部分WebView甚至直接忽略vh单位。
优先用min-h-[100dvh]替代min-h-screen
100dvh(dynamic viewport height)才是真正响应键盘弹出、地址栏收放的单位,iOS 16.4+ 和 Android Chrome 109+ 已稳定支持。但光换单位不够,必须配对布局逻辑:
-
min-h-[100dvh]只设最小高度,得配合flex flex-col才能让子项弹性分配空间 - 主内容区必须加
flex-1(或显式flex-grow flex-shrink-0 min-w-0),否则文字溢出会拉宽容器 - 固定底部(如按钮)要加
flex-shrink-0,否则键盘弹出会把它压扁 - 删掉
<meta>里height=device-height——这个参数会让所有vh类失效
老版本iOS兜底:用JS动态设--vh变量
当项目需兼容iOS 15及更早时,100dvh不可用,得靠JS读取真实可视高度:
- 监听
resize和orientationchange,用requestAnimationFrame防抖,避免频繁重排 - 首次渲染前就要执行一次
setVh(),否则首屏可能闪动或留白 - CSS中写
min-height: calc(var(--vh, 1vh) * 100),1vh是降级回退值 - 别用
window.innerHeight直接设body.style.height——iOS键盘收起后它延迟更新,会导致回弹错位
容易被忽略的Flex布局陷阱
哪怕用了100dvh,这几个点照样让布局塌陷:
- 侧边栏或弹窗用了
fixed但没加z-index和inset-0,父容器仍占文档流位置,撑高根容器引发滚动条,间接破坏flex高度计算 -
html或body写了h-full,但中间某层容器(比如<main></main>)没设flex-1或h-full,高度链就断了 - 多个输入框共用同一底部栏时,用
focusin/blur切class,必须统一用document.activeElement判断焦点状态,否则切换混乱
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











