iOS Safari 中 input 获取焦点后键盘顶起页面导致输入框被遮挡,主因是键盘弹出时滚动计算错误,应使用 focus 延迟 400ms 后调用 scrollIntoView({ block: 'nearest', inline: 'nearest' }),并避免 height: 100vh 和 unreliable resize 监听。

iOS Safari 中 input 获取焦点后键盘顶起页面,输入框被遮挡
这是 iOS Webview(尤其是 Safari)的典型表现:软键盘弹出时,Safari 会尝试滚动到聚焦元素,但经常计算错误,尤其在 position: fixed 或页面有缩放、viewport 设置不当时。不是所有输入框都触发,但底部表单、弹层内 input 最容易中招。
核心原因不是“没监听键盘”,而是 iOS 不暴露键盘高度,且 resize 事件不可靠,focus 时机与滚动行为不同步。
用 scrollIntoView + 延迟强制滚动最稳
别依赖 window.scrollTo 或 element.scrollIntoView({ behavior: 'smooth' }) 立即调用——iOS 在键盘动画开始前就执行了,结果还是被盖住。必须等键盘布局稳定后再滚动。
- 监听
input或textarea的focus事件 - 用
setTimeout延迟 300–500ms(iOS 键盘动画约 250ms,留余量) - 调用
element.scrollIntoView({ block: 'nearest', inline: 'nearest' }),避免smooth在某些 iOS 版本卡顿或失效 - 若输入框在
fixed容器里,确保该容器父级有可滚动区域(overflow-y: auto),否则scrollIntoView无效
input.addEventListener('focus', () => {
setTimeout(() => {
input.scrollIntoView({ block: 'nearest', inline: 'nearest' });
}, 400);
});
viewport 设置和 height: 100vh 是隐形雷区
iOS Safari 在键盘弹出时会动态压缩 vh 单位,但不会重排 height: 100vh 的元素,导致布局错乱、固定定位偏移。很多“键盘遮挡”其实是这个副作用引发的。
立即学习“前端免费学习笔记(深入)”;
- 避免在根容器或弹层上写
height: 100vh;改用min-height: 100vh或height: 100%(前提是父级有明确高度) -
viewport中禁用user-scalable=yes,并设height=device-height没用,iOS 忽略它;真正有效的是viewport-fit=cover(仅对 PWA/全屏模式生效) - 如果用了
meta name="viewport" content="width=device-width, initial-scale=1.0",别额外加maximum-scale,它会干扰键盘弹出时的视口重算
监听 resize 不可靠,但可以辅助判断键盘状态
iOS 的 resize 事件在键盘弹出/收起时确实会触发,但触发时机飘忽、频率高、且无法区分是键盘还是横竖屏引起。不能单独靠它做定位,但可结合 document.activeElement 做兜底。
- 监听
window.addEventListener('resize', ...) - 检查
document.activeElement是否为input/textarea,且getBoundingClientRect().bottom超出当前window.innerHeight,说明大概率被遮 - 此时再执行一次
scrollIntoView,作为 focus 延迟方案的补充 - 注意:不要在 resize 里反复 scroll,加防抖(如 100ms 内只执行一次)
真正难处理的是嵌套滚动、第三方 UI 组件(比如 Ionic、Framework7 的 modal)内部的输入框——它们可能劫持了 focus 行为,得查组件文档看是否提供 keyboardAttach 或 scrollAssist 配置项。










