grid容器键盘弹出时“上浮”是因100vh被浏览器锁定为初始视口高度,而visualviewport.height已压缩;改用100dvh可自动适配键盘状态与安全区域,配合min/max-height及flex-shrink: 0或grid-row: 1 / -1固定关键子项,并确保viewport meta正确。

为什么Grid容器在键盘弹出时会“上浮”或错位
不是Grid写错了,是height: 100vh被浏览器按初始视口锁定计算。iOS Safari和部分安卓WebView在软键盘弹出时既不更新window.innerHeight,也不触发resize事件,但实际可视区域(visualViewport.height)已压缩。结果就是Grid容器仍按全屏高渲染,内容被截断、弹窗悬空、底部输入框消失。
用100dvh替代100vh是最简解法
100dvh代表“当前可见视口高度”,键盘弹出时自动更新,且适配安全区域(如iPhone底部手势条)。Chrome 105+、Safari 16.4+ 已原生支持。
- 把所有
height: 100vh换成min-height: 100dvh; max-height: 100dvh; overflow-y: auto - 关键子项(如遮罩层、弹窗容器)加
flex-shrink: 0或设grid-row: 1 / -1固定占位,防止被压缩 -
viewportmeta必须正确:<meta name="viewport" content="width=device-width, initial-scale=1.0">,禁用maximum-scale=1或固定width
Grid布局中遮罩层被顶起怎么办
这是iOS Safari的典型表现:键盘呼出 → 100vh变小 → 遮罩层高度收缩 → 弹窗悬在半空。绕过vh单位比强行fix更可靠。
- 遮罩层不用
height: 100vh,改用min-height: 100%; height: -webkit-fill-available;(iOS专用) - 确保
html, body { height: 100%; },否则100%失效 - 更稳方案:监听
focusin/blur,用visualViewport?.height动态设style.height,并加防抖 - 别在
viewport里写height=device-height——它会强制缩放,干扰单位解析
兼容老版本Safari(dvh不可用)的降级策略
Safari 15.4以下不支持dvh,且grid-template-areas会被静默丢弃,导致display: grid退化为block。此时不能只靠CSS。
- 用
visualViewport?.height || window.innerHeight获取真实可视高度,JS动态设置容器style.height - 避免依赖
@supports (display: grid)判断——它不检测grid-template-areas是否可用 - 改用
grid-column/grid-row显式定位,例如grid-column: 1 / -1代替grid-area: header - 所有
gap写法统一为gap: 12px 16px,旧WebKit不识别row-gap/column-gap单独声明
visualViewport是唯一能实时反映用户所见高度的API,其余都是缓存值或初始快照。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











