页面底部输入框聚焦时吸底软键盘方案
0、参考布局


可能存在的问题
- 输入框未跟随软键盘弹起
- 输入框被顶起超过软键盘的高度
- 输入框被系统手势按钮遮挡
- 输入框没有被键盘挡住,但收起键盘后页面不会回落
- ios safari标签栏位于底部时 100vh并不是真实的高度,导致输入框被标签栏遮挡
- 输入框被顶起时,页面顶部被顶到了可视区域外
解决方案
1、Android
监听resize
事件
在Android中,软键盘弹起会导致页面高度变化,压缩页面,因此可以通过监听window
的resize
事件,并实时修改容器高度来保证输入框位于软键盘之上
window.addEventListener('resize', this.convertStyle);
convertStyle() {
this.$refs.container.style.setProperty('window.innerHeight', `${height}px`);
},
2、IOS
通过VisualViewport
监听resize
事件
在IOS中,软键盘的弹起并不会导致页面高度变化,而是会向底部添加一部分高度,使整个页面被顶起,并使底部fixed失效
IOS 13以后,新增了VisualViewport API 可以获取软键盘的高度
兼容性如图

通过监听VisualViewport
的resize
事件,并使用visualViewport
的height
实时修改容器高度来保证输入框位于软键盘之上
需要注意的是 safari当导航栏处于底部时,resize
事件的触发会很迟钝,导致输入框弹起稍慢,safari当导航栏处于顶部时无此问题,该问题在 ios16 Beta
中仍未修复
window.visualViewport.addEventListener('resize', this.convertStyle);
convertStyle() {
this.$refs.container.style.setProperty('window.visualViewport.height', `${height}px`);
},
3、安全区
iphoneX
以后因为全面屏底部触控条及刘海的存在,苹果牵头增加了env() safe-area-inset-XXX 属性 可以获取到安全区的高度
仅支持 ios 11.2 以上,安卓阵营部分浏览器最新版依然不支持该属性
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
还需要注意的是使用该属性 需要提前设置meta标签
<meta name="viewport" content="width=device-width, viewport-fit=cover">
4、safair 聚焦 弹起高度过高的问题
在使用VisualViewport
相关API重设容器高度的过程中,可能概率性出现页面被浏览器整体弹高的问题,在resize
事件中,强制滚动到顶部,可以解决该问题 需要注意的是滚动建议在resize
事件的10ms(测试出的兼容值)中执行,不然可能导致抖动、不生效等问题
window.visualViewport.addEventListener('resize', this.convertStyle);
convertStyle() {
this.$refs.container.style.setProperty('window.visualViewport.height', `${height}px`);
setTimeout(() => {
window.scrollTo(0, 1);
}, 10);
},
遗留问题
- 部分安卓浏览器没有设置安全区
- safari当导航栏处于底部时,输入框弹起卡顿