现象描述:iphone手机微信页面,用position: fixed;定位的input或textarea输入框,在获取输入焦点时,会被弹出的输入法软键盘遮挡,导致用户无法看到输入框,效果如图:
简化测试环境:删除页面其它元素,只保留输入框所在的评论框及最基本的控制评论框显示、隐藏的的交互js。
测试发现,输入法软软键盘弹出显示的状态下,即使页面上有加上css:html,body{height:100%;overflow:hidden;}样式控制,还是能看到页面有显示滚动条,往下滑动页面到最底时,输入框才会显示出来。
也就是说页面输入框的position: fixed;定位,在输入法软软键盘弹出显示的状态下失效了。
既然往下滑动页面到最底时,输入框能显示出来,那解决方法就出来了:
输入法软软键盘弹出时(即输入框获得焦点时),把页面的滚动条拉到底部即可,用js实现:
// iphone软键盘遮挡输入框
// 输入框不要加入blur事件,否则会导致"点击提交按钮,输入框无法正常收回"问题
if(navigator.userAgent.indexOf("iPhone")!=-1){
$(".form-input").focus(function(event) {
var _this = this;
typeof(timer) !="undefined" && clearTimeout(timer);
// 400:预留软键盘弹出时间
timer = setTimeout(function() {
document.body.scrollTop = document.body.scrollHeight;
}, 400);
})
}
这里要注意:
有加入setTimeout 400ms的预留软键盘弹出时间;
输入框不要加入blur事件,否则提交按钮会无法响应执行,直接导致出现"点击提交按钮,输入框无法正常收回"的问题。
这对于"fixed在页面底部的输入框"的情况,确实可以解决输入框被弹出的软键盘遮挡的问题,但是如果像一些页面如登录页,一般页面居中位置会显示一些如用户名、密码输入框的布局,用上面的代码可能会出现把最上面的输入框顶到页面可视区域顶部以外。
像这种情况我们可以使用js里面的Element.scrollIntoView() 方法,这方法可以让当前的元素滚动到浏览器窗口的可视区域内的顶部或底部,语法如下:
element.scrollIntoView(); // 等同于element.scrollIntoView(true)
element.scrollIntoView(alignToTop); // Boolean型参数:true/false
参数alignToTop是一个Boolean值:
如果为true,元素的顶端将和其所在滚动区的可视区域的顶端对齐。
如果为false,元素的底端将和其所在滚动区的可视区域的底端对齐。
// iphone软键盘遮挡输入框
if(navigator.userAgent.indexOf("iPhone")!=-1){
var scrTop = document.body.scrollTop;
$(".form-input").focus(function() {
var _this = this;
typeof(timer) !="undefined" && clearTimeout(timer);
// 400:预留软键盘弹出时间
timer = setTimeout(function() {
_this.scrollIntoView(false);
document.body.scrollTop+=70;
}, 400);
}).blur(function() { //设定输入框失去焦点时的事件
document.body.scrollTop = scrTop;
});
}
这里我们使用scrollIntoView(false),将.form-input输入框元素滚动到浏览器窗口的可视区域内的底部,然后再将页面的scrollTop值自加70px,使得input框与页面可视区域的底部保持70px的距离,输入文字时,视觉上更合适。
另外,要注意到setTimeout延时跟停止输入,input失去焦点时的blur事件也是必须的,这可保证scrollIntoView(false)定位正确 和 含有input输入框的弹出层在该input框blur时能够还原回原先的定位位置!
参考文档:
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollIntoView