软键盘弹出导致输入框被顶出可视区,核心解法是focus时调用scrollintoview({block:'nearest',inline:'nearest'}),ios需动态修正fixed元素bottom值,根容器用100dvh+flex布局兜底,blur时scrollto归位。

软键盘弹出把 input 顶上去,本质是浏览器对视口(viewport)的处理逻辑被干扰:iOS 压缩布局视口、Android 挤压 window.innerHeight,导致 fixed/absolute 元素错位、输入框不可见。解决不能靠“堵”,而要分场景主动适配。
用 scrollIntoView 主动滚动到输入框
这是兼容性最好、代码最轻量的核心手段:
- 必须在 input 的 focus 事件中调用,不是 click 或 touchstart(时机太早,焦点未生效)
- 推荐参数:
scrollIntoView({ block: 'nearest', inline: 'nearest' }),避免过度滚动遮挡光标 - 老版微信 X5 内核不支持
behavior: 'smooth',直接去掉更稳妥 - 对
type="text"、type="tel"等触发型输入框生效,hidden或disabled不需处理
动态修正 bottom 值应对 iOS fixed 失锚
iOS Safari 下 fixed 元素会“降级”为 relative 行为,底部操作栏容易悬空:
- focus 时立即执行
inputRef.getBoundingClientRect().bottom - 若该值 ≤ 0 或
window.innerHeight * 0.2,说明输入框已接近或超出可视区底部 - 将差值(如
window.innerHeight - inputRect.bottom)设为底部区域的style.bottom - blur 时清空 bottom,还原为初始值(如 0 或 auto)
容器层用 100dvh + Flex 布局兜底
避免弹窗/表单整体被键盘推移,关键在根容器不依赖视口锚点:
- 父容器设
display: flex; flex-direction: column; min-height: 100dvh - 内容区加
flex: 1; overflow-y: auto,确保可滚动不撑高 - 底部操作区加
flex-shrink: 0,防止被压缩 -
必须配合
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">,否则dvh单位无效
收起键盘后恢复页面位置
键盘关闭时页面常卡在偏移态,需主动归位:
- 监听
focusout或blur事件(比 resize 更可靠,尤其 iOS 不触发 resize) - 用
window.scrollTo({ top: savedScrollTop, behavior: 'instant' })立即跳转(避免 smooth 动画延迟) - 建议搭配防抖(300ms),防止连续 blur 触发多次
- 若页面有自定义滚动容器(如 better-scroll),需同步重置其内部 scrollTop











