在ios中,position:fixed的效果并不理想,最突出的莫过于 底部固定定位+input 所出现的问题了。
一个div固定定位于底部
当div内的input获取焦点后,键盘弹出,div就会被推到中间这位置
这效果并不是我们想要看见的。究其原因,大致就是软键盘弹出后fixed失效了,变成了absolute,而键盘推出时使页面发生了滚动,所以就出现了这种现象。
为了解决这个问题,我到网上查找了各种各样的相关文章,虽然并非没有找到有用的信息,但有效且完整的方案一个都没找到。最后,我只能根据这些有用的信息,加上自己的思考,想出了一个就目前而言比较可行的、完整的方案。
结构
<div class="header"></div>
<div class="main" id="main">
<div class="content"></div>
</div>
<div class="footer">
<input type="text" />
</div>
样式
.header,.footer{
position:absolute;
left:0;
right:0;
height:50px;
z-index:999;
background-color:#333;
}
.header{
top:0;
}
.footer{
bottom:0
}
.main{
position:absolute;
left:0;
top:50px;
right:0;
bottom:50px;
overflow-y:auto;
-webkit-overflow-scrolling:touch; //ios中,通过overflow产生的scroll在滑动时会不流畅,添加上这个属性就能使其流畅滑动
}
.content{
height:2000px;
}
使用这种方法,最外层不能定位,因为低版本ios不支持fixed,为了兼容,一般使用absolute,如果外层定位了,就不能使用absolute代替fixed了。
上面这个做法我是从网上看来的,但只这样写的话会出现问题,就是滑动时,滚动条还没到达边界就把下方或上方的背景给拉出来,非常影响体验。
所以,我们需要用js来控制一下。
function moveAdjustment(domId){
document.documentElement.ontouchmove=function(e){
e.preventDefault();
};
var wrap=document.getElementById(domId);
wrap.addEventListener('touchstart',function(e){
var startPoint=e.touches[0].clientY;
wrap.ontouchmove=function(e){
var movePoint=e.touches[0].clientY;
var nowScroll=wrap.scrollTop;
var wholeScroll=wrap.scrollHeight-wrap.clientHeight;
//注意,这里的对象不能是e.target,因为禁止冒泡之后这个e就没用了。
if(nowScroll==0){
if(startPoint<movePoint){
e.preventDefault();
}else{
e.stopPropagation();
};
}else if(nowScroll==wholeScroll){
if(startPoint>movePoint){
e.preventDefault();
}else{
e.stopPropagation();
}
}else if(nowScroll>0 && nowScroll<wholeScroll){
e.stopPropagation();
}else{
e.preventDefault();
};
};
},false);
};
moveAdjustment('main');
这样,我们的这个问题就算基本解决了。