滚动穿透问题的解决方案

本文介绍了解决移动端弹出层滑动导致的滚动穿透问题的三种方法。包括使用preventDefault阻止默认事件、通过添加class实现固定效果及改进版方案,确保原页面滚动位置不丢失。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

滚动穿透问题体现在移动端弹出层滑动时,导致弹框下面页面的滚动。

方案一:

使用 preventDefault 阻止浏览器默认事件:

var modal = document.getElementById('modalBox');
modal.addEventListener('touchmove', function(e) {
    e.preventDefault();
}, false);

该方案适用于弹框内容高度小于屏幕高度,即弹框内容不可滑动的场景。touchmove 比 touchstart 更加合适。因为 touchstart 会连点击事件都阻止。

 

方案二:

给 overflow: scroll;的元素加上一个 class (以 body 元素为例)。退出的时候去掉这个 class

// css 部分
modal_open {
    position: fixed;
    height: 100%;
}

// js 部分
document.body.classList.add('modal_open');
document.body.classList.remove('modal_open');

该解决方案会带来新的麻烦,如果原页面不滚动的情况下,使用很完美,如果原页面滚动到一定的位置,使用该方案后,关闭弹框原页面会出现滚动位置丢失,即scrollTop 属性值会变为 0。需优化该方案为方案三。

 

方案三:

对方案二进行优化,在弹框弹出时,对原页面滚动位置进行保存,弹框关闭前,将原页面滚动的位置设置回去。

// css 部分
.modal_open {
  position: fixed;
  height: 100%;
}

// js 部分
var ModalHelper = (function(bodyClass) {
    var scrollTop;
    return {
        afterOpen: function() {
            scrollTop = document.scrollingElement.scrollTop  ||
                        document.documentElement.scrollTop || 
                        document.body.scrollTop;
            document.body.classList.add(bodyClass);
            document.body.style.top = -scrollTop + 'px';
        },
        beforeClose: function() {
            document.body.classList.remove(bodyClass);
            document.scrollingElement.scrollTop = document.documentElement.scrollTop = document.body.scrollTop = scrollTop;
        }
    };
})('modal_open');

// method
modalSwitch: function(){
    let self = this;
    if( self.switchFlag === 'close' ){
        ModalHelper.afterOpen();
        self.switchFlag = 'open';
    }else{
        ModalHelper.beforeClose();
        self.switchFlag = 'close';
    }
}

方案二达到的效果:

  1. 弹窗滚动的时候,下方的原页面是固定的无法滚动;
  2. 页面的滚动位置不会丢失;
  3. 页面有 scroll 事件;

 

参考:

https://juejin.im/post/5c2dc9cce51d45690a254b79

developer.mozilla.org/en-US/docs/…

uedsky.com/2016-06/mob…

vue-noscroll-layer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值