William's Blog

解决移动端网页开发“滚动穿透”问题

问题背景

  在移动端网页中,经常会以弹层的形式来展示信息给用户。在开发弹层时经常会遇到这样一个问题:当用户手指在弹层上滑动时,弹层下面的内容也会跟随手指的滑动一起滚动。这就是移动端网页的 “滚动穿透” 问题。

问题产生原因

  当用户手指在弹层上滑动时,默认触发了浏览器的 “scroll” 事件,事件冒泡至body元素,于是就产生了 “滚动穿透” 效果。

问题解决方案

  针对移动端页面”滚动穿透”的问题,目前主要有两种解决方案:
  (1)在touchmove事件处理函数中使用preventDefault()阻止事件的默认动作。当用户手指在弹层上滑动时,浏览器不再触发 “scroll” 事件,“滚动穿透” 现象也就不再发生。但是该解决方案不适用于弹层需要实现滚动的场景。
  (2)当发起弹层时,设置body元素的position属性为fixed,并且设置body元素向上的偏移量等于此时其已经滚动的距离;当关闭弹层时,恢复body元素的相关属性即可。该方案与方案(1)相比,可以适用于弹层包含滚动的场景,是一个相对完美的解决方案。该方案的核心处理函数的示例代码如下:

// 发起弹层时调动
function fixBody() {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    document.body.style.position = 'fixed';
    document.body.style.top = -scrollTop + 'px';
    // 设置body宽度等于viewport的宽度,防止body子元素宽度大于视口宽度时布局错乱
    document.body.style.width = '100%';
}

// 关闭弹层时调用
function relaxBody() {
    // 清空position属性
    document.body.style.position = '';
    // 恢复scrollTop
    document.body.scrollTop = document.documentElement.scrollTop = -parseFloat(document.body.style.top);
    // 清空top属性
    document.body.style.top = '';
    // 清空width属性
    document.body.style.width = '';
}

小提示

  对于PC端页面来说,可以设置body元素的overflow属性的值为hidden来解决弹层的 “滚动穿透” 问题。该方案只适用于PC端页面,不适用于移动端页面。


William

本博客作者 William 现任职于北京贝壳找房,从事web前端开发相关工作。
您可以通过Email与他取得联系