移动端出现滚动穿透问题完美解决方案

开发Cuteen时,侧边栏再一次遇到了滚动穿透问题。话说这个移动端滚动穿透问题很早就遇到了,当时采用的是弹出框出现时,记录滚动位置并让body禁止滚动,弹出框消失时,body滚动到记忆位置,但是弹出框是居中的一小块,其余部分使用黑色半透明的遮罩蒙版覆盖,所以弹出框时用户还是可以看见列表位置变成第一列,弹出框消失时列表又变到记忆位置,这样的体验非常不好,今天利用新方法,顺利解决了这个问题,顺便在此记录一下处理方法,希望能帮到需要帮助的人:

1.更换滚动dom的方法

经测试,当body滚动时,操作弹出层才会触发body的滚动,如果是其他dom滚动的话,在操作弹出层的时候不会触发该dom的滚动,所以把滚动内容的容器改成其他dom就可以了,如下:

<body> 
 <ui-view class="container" style="display: block; height: 100%; overflow: auto"></ui-view> 
 <div id="showDetail"></div> 
</body>

这种办法最是简单有效,但是有可能和手势组件冲突,最后我使用的是下面这种方法:

2.移动body

这个方法来自:移动端滚动穿透问题完美解决方案

思路是弹出框弹出前,记录目前滚动位置,给body加上position: fixed; 然后使body的top距离为负的滚动距离即可(使屏幕显示的区域不变);弹出框消失时,移除position: fixed; ,设置body滚动位置为记录位置,这样就解决了我开头提到的位置跳转的问题:屏幕显示的内容始终不变,体验效果棒棒的

Css部分:

body.modal-open {
    position: fixed;
    width: 100%;
}

Js部分:

var ModalHelper = (function(bodyCls) {
  var scrollTop;
  return {
    afterOpen: function() {
      scrollTop = document.scrollingElement.scrollTop;
      document.body.classList.add(bodyCls);
      document.body.style.top = -scrollTop + 'px';
    },
    beforeClose: function() {
      document.body.classList.remove(bodyCls);
      // scrollTop lost after set position:fixed, restore it back.
      document.scrollingElement.scrollTop = scrollTop;
    }
  };
})('modal-open');

3.利用属性 overflow: hidden

这个就是我原来采用的方法:

.no-scroll {
    overflow: hidden;
    height: 100%;
}

页面弹出层上将 .no-scroll 添加到 html 上,禁用 html 和 body 的滚动条,使用js来记录滚动位置,弹出框关闭时还原,不建议采用。

4.利用 touchmove + preventDefault

这种也是简单快速的处理办法,直接接听弹出层dom的touchmove 事件,然后阻止默认行为即可,但是这种方法使得弹出层dom的滚动事件也一并失效,所以当你的弹出层无需滚动时,这不失是一种快捷有效的方法:

modal.addEventListener('touchmove', function(e) {
  e.preventDefault();
}, false);
打赏
评论区
头像
    头像
    春风
      

    完美解决问题,感谢博主