作者:诀九
前言
在移动端使用弹窗时,我们会经常遇到这种现象:滑动弹窗时,遮罩层下面的背景(body)也会跟随滑动,带来的用户观感体验很差。
市面上的解决方案大部分通过阻止touchmove默认事件执行event.preventDefault()解决,但是这种方案存在兼容性,不能对所有浏览器都有效,而且如果弹窗本身存在滚动(如活动规则弹窗),这种解决方案并不能阻止背景滑动,如下图活动规则弹窗所示:
终极解决方案
线上代码,超级简短
// 展示弹窗时,阻止背景滚动function stopScroll () { let top = document.body.scrollTop ||
document.documentElement.scrollTop; document.body.style.position = 'fixed'; document.body.style.top = `${-1 * top}px`;}// 隐藏弹窗时,恢复背景的滚动function recoverScroll () { let top = -parseInt(document.body.style.top); document.body.style.position = 'static'; document.body.style.top = 0; window.scrollTo(0, top);}// 注意事项// 设置fixed后页面元素会发生偏移,通过设置body样式可以解决这个问题body { width: 100%;}
下面我们分析下原理:
该方案主要是利用position: fixed特性,展示弹窗时给body设置该样式,就能阻止body的滚动。
但是body设置fixed样式后会导致页面自动滚动到顶部,不会固定在原来的浏览位置,导致关闭弹窗后,还要从头滚动页面继续浏览,用户体验不好。
所以,我们最终要解决的问题就转化为:body设置fixed样式后,让body停留在原来的浏览位置,而不是自动滚动到顶部。
明确了要达到的目的,就很好解决了。
- 在body设置fixed样式之前,先记录下滚动条的偏移位置。
let top = document.body.scrollTop || document.documentElement.scrollTop;
- body设置fixed样式后,页面会滚动到顶部,我们通过设置top,让body偏移到原来的浏览位置就可以了。注意,这里的top要设置为负数。
document.body.style.top = `${-1 * top}px`;
- 关闭弹窗,恢复页面滚动,基本上是一个逆向思路。恢复body默认的top、position样式,把页面滚动到原来的偏移位置。
let top = -parseInt(document.body.style.top);document.body.style.position = 'static';document.body.style.top = 0;window.scrollTo(0, top);
注意事项
在设置body为fixed后,有些页面元素会发生偏移,我们给body加个宽度限制就可以解决这类问题了
body { width: 100%}
总结
该方案基本上能够完美解决我们移动端遇到的背景滚动问题,对短弹窗和长弹窗(弹窗自身有内容滚动)都适用,不存在兼容性问题。我在做活动页的过程中,都是用的这个方法,实践证明是可靠的,放心使用。
作者:诀九