Web移动端Fixed布局的解决方案

转载于EFE博客,这是一篇非常有价值的文章,做移动端基本跑不了会遇到这篇文章提到的问题。

移动端业务开发,iOS下经常会有fixed元素和输入框(input元素)同时存在的情况。但是fixed元素在有软键盘唤起的情况下,会出现许多莫名其妙的问题。这篇文章里就提供一个简单的有输入框情况下的fixed布局方案。

iOS下的Fixed+InputBUG现象

让我们先举个栗子,最直观的说明一下这个BUG的现象。常规的fixed布局,可能使用如下布局(以下仅示意代码):

bodyclass=layout-fixed!--fixed定位的头部--header/header!--可以滚动的区域--main!--内容在这里...--/main!--fixed定位的底部--footerinputtype=textplaceholder=Footer.../buttonclass=submit提交/button/footer/body

对应的样式如下:

header,footer,main{display:block;}header{position:fixed;height:50px;left:0;right:0;top:0;}footer{position:fixed;height:34px;left:0;right:0;bottom:0;}main{margin-top:50px;margin-bottom:34px;height:px}

然后看起来就是下面这个样子。拖动页面时header和footer已经定位在了对应的位置,目测没问题了。

fixed定位

但接下来问题就来了!如果底部输入框软键盘被唤起以后,再次滑动页面,就会看到如下图所示:

我们看到fixed定位好的元素跟随页面滚动了起来…fixed属性失效了!

这是为什么呢?简单解释下:软键盘唤起后,页面的fixed元素将失效(即无法浮动,也可以理解为变成了absolute定位),所以当页面超过一屏且滚动时,失效的fixed元素就会跟随滚动了。

这便是iOS上fixed元素和输入框的bug。其中不仅限于type=text的输入框,凡是软键盘(比如时间日期选择、select选择等等)被唤起,都会遇到同样地问题。

虽然isScroll.js可以很好的解决fixed定位滚动的问题,但是不在万不得已的情况下,我们尽量尝试一下不依赖第三方库的布局方案,以简化实现方式。这里抛砖引玉作为参考。

解决思路:

既然在iOS下由于软键盘唤出后,页面fixed元素会失效,导致跟随页面一起滚动,那么假如——页面不会过长出现滚动,那么即便fixed元素失效,也无法跟随页面滚动,也就不会出现上面的问题了。

那么按照这个思路,如果使fixed元素的父级不出现滚动,而将原body滚动的区域域移到main内部,而header和footer的样式不变,代码如下:

bodyclass=layout-scroll-fixed!--fixed定位的头部--header/header!--可以滚动的区域--maindivclass=content!--内容在这里...--/div/main!--fixed定位的底部--footerinputtype=textplaceholder=Footer.../buttonclass=submit提交/button/footer/body

header,footer,main{display:block;}header{position:fixed;height:50px;left:0;right:0;top:0;}footer{position:fixed;height:34px;left:0;right:0;bottom:0;}main{/*main绝对定位,进行内部滚动*/position:absolute;top:50px;bottom:34px;/*使之可以滚动*/overflow-y:scroll;}main.content{height:px;}

这样再来看一下:

fixed定位

在原始输入法下,fixed元素可以定位在页面的正确位置。滚动页面时,由于滚动的是main内部的div,因此footer没有跟随页面滚动。

上面貌似解决了问题,但是如果在手机上实际测试一下,会发现main元素内的滚动非常不流畅,滑动的手指松开后,滚动立刻停止,失去了原本的流畅滚动特性。百度一下弹性滚动的问题,发现在webkit中,下面的属性可以恢复弹性滚动。

-webkit-overflow-scrolling:touch;

在main元素上加上该属性,嗯,丝般顺滑的感觉又回来了!

main{/*main绝对定位,进行内部滚动*/position:absolute;top:50px;bottom:34px;/*使之可以滚动*/overflow-y:scroll;/*增加该属性,可以增加弹性*/-webkit-overflow-scrolling:touch;}

另外,这里的header和footer使用的是fixed定位,如果考虑到更老一些的iOS系统不支持fixed元素,完全可以把fixed替换成absolute。测试后效果是一样的。

至此一个不依赖第三方库的fixed布局就完成了。

Android下布局

谈到了iOS,也来简单说一下Android下的布局吧。

在Android2.3+中,因为不支持overflow-scrolling,因此部分浏览器内滚动会有不流畅的卡顿。但是目前发现在body上的滚动还是很流畅的,因此使用第一种在iOS出现问题的fixed定位的布局就可以了。

如果需要考虑Android2.3以下系统,因为不支持fixed元素,所以依然要需要考虑使用isScroll.js来实现内部滚动。

其实在fixed和输入框的问题上,基本思路就是:由于fixed在软键盘唤起后会失效,导致在页面可以滚动时,会跟随页面一起滚动。因此如果页面无法滚动,那么fixed元素即使失效,也不会滚动,也就不会出现bug了。

所以可以在这个方面去考虑解决问题。

其他的一些细节处理

在细节处理上,其实还有很多要注意的,挑几个实际遇到比较大的问题来说一下:

有时候输入框focus以后,会出现软键盘遮挡输入框的情况,这时候可以尝试input元素的scrollIntoView进行修复。

在iOS下使用第三方输入法时,输入法在唤起经常会盖住输入框,只有在输入了一条文字后,输入框才会浮出。目前也不知道有什么好的办法能让唤起输入框时正确显示。这暂时算是iOS下的一个坑吧。

有些第三方浏览器底部的工具栏是浮在页面之上的,因此底部fixed定位会被工具栏遮挡。解决办法也比较简单粗暴——适配不同的浏览器,调整fixed元素距离底部的距离。

最好将header和footer元素的touchmove事件禁止,以防止滚动在上面触发了部分浏览器全屏模式切换,而导致顶部地址栏和底部工具栏遮挡住header和footer元素。

在页面滚动到上下边缘的时候,如果继续拖拽会将整个View一起拖拽走,导致页面的“露底”。

fixed定位

为了防止页面露底,可以在页面拖拽到边缘的时候,通过判断拖拽方向以及是否为边缘来阻止touchmove事件,防止页面继续拖拽。

以上面内滚动layout-scroll-fixed布局为例,给出一段代码作为参考:

//防止内容区域滚到底后引起页面整体的滚动varcontent=document.querySelector(main);varstartY;content.addEventListener(touchstart,function(e){startY=e.touches[0].clientY;});content.addEventListener(touchmove,function(e){//高位表示向上滚动//底位表示向下滚动//1容许0禁止varstatus=11;varele=this;varcurrentY=e.touches[0].clientY;if(ele.scrollTop===0){//如果内容小于容器则同时禁止上下滚动status=ele.offsetHeight=ele.scrollHeight?00:01;}elseif(ele.scrollTop+ele.offsetHeight=ele.scrollHeight){//已经滚到底部了只能向上滚动status=10;}if(status!=11){//判断当前的滚动方向vardirection=currentY-startY0?10:01;//操作方向和当前允许状态求与运算,运算结果为0,就说明不允许该方向滚动,则禁止默认事件,阻止滚动if(!(parseInt(status,2)parseInt(direction,2))){stopEvent(e);}}});

点击下方阅读全文查看原文

赞赏

长按







































吡美莫司乳膏治白癜风效果如何
治疗白癜风最好医院



转载请注明:http://www.guyukameng.com/jsp/8269.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了