移动端 fixed 元素被软键盘顶起是因锚定视觉视口,iOS 16.4+ 可用 env(keyboard-inset-bottom) 原生避让,安卓需 sticky 或 absolute+JS 动态适配,三者叠加并处理 iOS 键盘收起延迟与 focusin 时机才能稳定避让。

移动端 position: fixed 元素(尤其是底部按钮、输入框旁操作栏)被软键盘顶起,不是 CSS 写错了,而是浏览器把 fixed 锚定在「视觉视口(visual viewport)」上,而键盘弹出会压缩这个视口——但元素定位值没重算,结果就浮在键盘上方空白处。iOS 和安卓 WebView 行为不一致,纯 CSS 无法感知键盘状态,必须组合使用环境变量、定位切换和高度监听。
用 env(keyboard-inset-bottom) 做 iOS 原生避让(16.4+)
这是目前最干净的方案,零 JS,但仅限 iOS Safari 16.4 及以上支持:
- 必须在
中启用适配: - 底部元素写法:
bottom: env(keyboard-inset-bottom, 0px);—— 键盘弹出时自动上浮,收起后回退到0px - 必须用
@supports降级,否则旧版 Safari 会忽略整条规则甚至解析失败:@supports (bottom: env(keyboard-inset-bottom)) { .btn-footer { bottom: env(keyboard-inset-bottom, 0px); } } - 安卓完全不支持该变量,不能只靠它;也别和
svh混用,比如bottom: calc(0px + 100svh)是错的——svh是高度单位,env(keyboard-inset-bottom)是偏移量,语义不同
用 position: sticky 替代 fixed(推荐首选)
如果你的按钮本就紧贴内容流底部(如聊天输入框、评论提交区),sticky 更自然、更少副作用:
- 设
position: sticky; bottom: 0;,父容器需有明确高度(如min-height: 100vh)且允许内部滚动 - 它不脱离文档流,不会被键盘“悬空”顶起,也不受
transform等属性引发的层叠上下文干扰 - 兼容性已足够好:iOS 15.4+、Android Chrome 90+ 均支持;旧版可渐进增强为
absolute+bottom: 0 - 注意别在父容器上加
overflow: hidden或transform,否则sticky会失效
用 position: absolute + JS 动态计算(兼容性最广)
这是兜底能力最强的方案,适用于所有浏览器,包括老安卓 WebView 和 iOS 15.3:
- 根容器设
position: relative; min-height: 100vh;,并禁用 body 滚动:body { overflow: hidden; } - 底部区域用
position: absolute; bottom: 0; width: 100%; - 监听
focusin到或,用setTimeout(() => { ... }, 0)确保 DOM 更新完成后再读取getBoundingClientRect().bottom - 计算方式是:
window.innerHeight - input.getBoundingClientRect().bottom,然后赋给footer.style.bottom -
blur后必须恢复bottom: 0,且加setTimeout(..., 100),避免 iOS 键盘收起动画未结束就重置
监听 resize + window.innerHeight 做兜底判断
所有 JS 方案都得靠它补漏,因为 focusin/blur 会漏掉“粘贴菜单唤起但键盘未弹出”等场景:
- 页面加载时缓存初始
window.innerHeight,记为baseHeight - 监听
window.addEventListener('resize', handler),比较当前高度与baseHeight:差值 > 150px 基本可判定键盘已弹出 - iOS Safari 的
resize常延迟或抖动,必须加防抖(setTimeout+clearTimeout),延迟 300ms 再执行定位逻辑 - 不要在
resize回调里直接操作style.position,改用预设 CSS 类(如.footer--keyboard-active),减少重排压力 - 别依赖
document.body.clientHeight或document.documentElement.scrollHeight,它们在键盘弹出期间可能未及时更新,window.innerHeight才是唯一可信指标
真正难的不是选哪个方案,而是三者叠加:用 env(keyboard-inset-bottom) 覆盖新 iOS,sticky 作为默认行为,absolute + resize + focusin 做全平台兜底。最容易被忽略的是 iOS 键盘收起后 window.innerHeight 不立即恢复,以及 focusin 触发时机早于布局完成——这两个点不处理,任何方案都会闪一下或错位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











