记一次移动端滑动穿透的问题解决

移动端当有fixed蒙层遮罩时,在屏幕上滑动能够滑动背景下的内容,这就是滚动穿透问题。

1、问题还原



  
内容部分
弹出框

css就省略了,内容部分是超过一屏的长度的,弹出框采用绝对定位展示在可视区域的固定位置,遮罩是加在body元素上的。滑动页面会出现滑动穿透的问题,遮罩下的内容会跟着滑动。

2、问题分析

出现滑动穿透的问题是滚动条在body元素上,而滑动的时候body自然是可以响应的。那么将结构改变一下:



  
内容部分
弹出框

为了不让滚动条加在body元素上,还需要做如下处理:

body {
height: 100%;
}
.content {
height: 100%;
overflow: auto;
}
. overflow-hidden {
overflow: hidden
}

在弹出框出现时需要把overflow-hidden类加在根div元素上。弹出消失时移除。

3、总结

这里po一个搜到的常规解决穿透的方案:

解决方案原理:禁用body的滚动条,由于滚动条的位置会丢失,所以需要在展示弹窗之前保存滚动条的位置,隐藏弹窗时恢复滚动条的位置。

首先定义class来禁用滚动条

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

然后完成保存并恢复滚动条的工作:

/**
  * ModalHelper helpers resolve the modal scrolling issue on mobile devices
  * https://github.com/twbs/bootstrap/issues/15852
  * requires document.scrollingElement polyfill https://github.com/yangg/scrolling-element
  */
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');

然后在弹出层显示时调用ModalHelper.afterOpen(),在隐藏弹出层时调用ModalHelper.beforeClose()

不过这种方式较麻烦了,能够采用简单的方式解决还是最好的。

4、两个兼容问题

1.在IOS上惯性滑动失效

.content {
  -webkit-overflow-scrolling: touch; /* 解决在IOS上滚动惯性失效的问题 */
}

2.在IOS上非交互性元素的点击事件失效

非交互性元素:没有显式绑定点击等事件处理函数的元素。

简单的解决方案是给元素添加cursor: pointer使之成为交互元素

但是这又会带来另一个问题:所有设置cursor: pointer的元素在webkit内核的浏览器中点击时会有蓝色背景,可以如下设置来取消蓝色背景:

*{
  -webkit-tap-highlight-color: transparent; /* 解决设置cursor:pointer的元素点击出现蓝色背景的问题 */
}

后话

在ios中有一个默认的效果是双击title回到顶部,如果滚动条不是在body元素上,那么这个效果将失效。

你可能感兴趣的:(记一次移动端滑动穿透的问题解决)