8

web移动端浮层滚动阻止window窗体滚动JS/CSS处理

 2 years ago
source link: https://www.zhangxinxu.com/wordpress/2016/12/web-mobile-scroll-prevent-window-js-css/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=5844
本文可全文转载,但需得到原作者书面许可,同时保留原作者和出处,摘要引流则随意。

更新于2018-08-10
差不多快2年过去了,Chrome已经开始支持这么一个CSS属性,名为overscroll-behavior,可以设置滚动到边界时候的页面行为。

一、温故而知新

之前有写过在PC端“子元素scroll父元素容器不跟随滚动”的实现,原理是滚动到边缘通过preventDefault()阻止浏览器的默认行为达到我们想要的效果。

最近做移动端项目,遇到个类似的需求,就是,在众多web浏览器中,当我们出现一个浮层,浮层里面也有滚动条的时候,且有部分背景半透明的时候,就会发现,当我们滚动浮层里面的小滚动条的时候,背后整个页面都跟着一起滚走了。

后来,以为会和PC端一样,直接给<html>标签设置一个overflow:hidden声明就可以干掉窗体的滚动条,结果发现自己有些天真了。

后来经过一些研究以及测试,得到了下面这种双管齐下的处理方法。

二、阻止移动端窗体滚动的JS/CSS处理

首先CSS层面,在<html>标签上增加一个类名,例如noscroll,然后配合如下CSS和JS代码:

.noscroll,
.noscroll body {
    overflow: hidden;
}
.noscroll body {
    position: relative;
}

然后,当浮层出现的时候:

$('html').addClass('noscroll');

当浮层隐藏的时候:

$('html').removeClass('noscroll');

可以让一部分浏览器的窗体不能滚动,但不包括Safari等浏览器,怎么办呢?

我们可以在浮层touchmove的时候,阻止默认事件达到避免滚动的问题,例如:

$('aside').on('touchmove', function(event) {
    event.preventDefault();
});

这种处理兼容性强,效果最好,但是有一个问题,就是如果浮层自己也有滚动,那么这种处理会让浮层里面自己的滚动行为也无法触发,因此,我们的处理要更进一步,如下:

  1. 当手指touchstart的元素不是滚动容器同时不失容器的子元素的时候,阻止默认行为,;
  2. 如果手指touchstart的元素是滚动容器或者容器子元素的时候,不阻止默认行为,但不包括滚动到容器边缘的时候。

根据上述原理,我自己抽象了一个简单的方法,方法名和语法如下,完整代码见这里

$.smartScroll(container, selectorScrollable);

依赖Zepto.js或者jQuery.js,其中:
container表示委托的浮层容器元素($包装器对象),或者页面其他比较祖先的元素,但是,非常不建议使用$(document)或者$(document.body)等对象作为委托容器,因为可能会出现类似下面这样的错误提示:

Unable to preventDefault inside passive event listener due to target being treated as passive.

浏览器可能会把这些窗体元素的组织默认行为认为是不可取的消极的,会不被支持。

selectorScrollable表示container中可以滚动的元素的选择器,表示真正的滚动的主体。

$.smartScroll()方法的完整代码可以参见演示demo,您可以狠狠地点击这里:浮层元素滚动窗体不滚动的CSS/JS处理demo

或者扫码访问:

演示文档的二维码地址

综合了上面的CSS noscroll处理和JS的$.smartScroll()方法处理。

demo页面有如下图所示的两个按钮:

阻止滚动按钮示意

其中,上面的按钮,仅仅是采用了CSS限制,会发现,手指移动左侧半透明边缘的时候,例如在iPhone的Safari浏览器下,后面的页面内容也被滚走了;但是,一旦点击下面的测试按钮,会发现,此时,仅仅浮层里面的容器可以滚动,一旦到了边缘或者其他任何地方,都不会引起后面页面内容的滚动。

移动半透明背景色与移动

这就是我们要实现的,浮层元素自己可以滚动,窗体不能滚动的效果。

更新于2017-01-12
这样的,此方法可以让95%+的场景都是正常。根据自己工作人员测试,有部分Android还会有微移的情况,可以试试边缘判断更钝一点。不过,最终我们并没有追求100%设备完全完美,这是成本和场景后权衡之后的一种策略。

三、2016年的最后一条结束语

12月份是个超级忙碌的1个月份,只能趁着元旦周末2016年的最后1天再写点什么。

2016年依然是非常忙碌奋斗的一年,每天都在学习与进步。不过而大多数人不一样,学习的重心依然是CSS基础知识,事无巨细和深入到底两个方向,其实基本上都没什么实用价值的东西,兴趣所在而已。并没有过多关注上层建筑,一些流行事物也就看看而已;没有参加任何论坛会议之类,没有任何的社交和抛头露面,坚持分享和知识传播,无论是公司内还是对外;也几乎没有花精力在开源项目上,无论是自己的还是协助贡献。以保证有限的精力能够专注在1~2件事情上。依旧奋斗在项目一线,尽量避免面试,人员管理这些琐碎的事情,目前对当领导不感兴趣,我只是个打杂的,所以,小伙伴写邮件提问与交流的时候,不要叫我领导,我不是;也不要叫我大神,更不是。

虽然工作快7年,但是还是认为自己在积累阶段,希望在2017年可以慢慢开点花结点果。可能因为钓鱼的缘故,我是个非常耐得住性子的人,不急功近利,不心浮气躁,保持自由,不被外在环境束缚,按照自己的目标和规划走。

就这些吧~

祝大家2017年升职加薪,幸福美满!

(本篇完)1f44d.svg 是不是学到了很多?可以分享到微信
1f44a.svg 有话要说?点击这里


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK