-
Notifications
You must be signed in to change notification settings - Fork 52
移动端滚动穿透问题
June Deng edited this page May 24, 2018
·
10 revisions
定义:移动端弹出fixed弹窗的话,在弹窗上滑动会导致下层的页面跟着滚动,这个叫 “滚动穿透”
在弹出层的touchstart
事件中调用preventDefault
这种方法不可取,至少有3个缺点:
- 如果弹出层本身是有滚动(条)的话,将会导致弹出层无法滚动,此时用这种方法无异于饮鸩止渴。
- 一个很常见的场景,点击弹出层,弹出层消失掉,此时也无法触发弹出层的点击回调事件。
- 弹出层内的任何事件都执行不了了。
此解决方案是解决方案1的升级版。
在弹出层的touchmove
(注意区别)事件中调用preventDefault
这种解决办法没有了第一种解决办法的 2, 3 缺点。适用于弹出层本身有没有滚动(条)。
设置body{overflow:hidden;}
缺点:经测试,在PC上支持良好,但是在IOS端,跟没有设置是一样的,完全不起任何作用!。
这种解决方案适用于PC端。
设置 html,body{overflow:hidden;}
在PC和移动端都能禁止掉下层的滚动。
缺点:
- 滚动位置丢失!页面会回到顶部!
- 页面的背景还是能够有滚的动的效果(这个我没遇到)。
可通过js来fix这个缺点,在弹出层出现时,记录页面的scrollTop
,当弹出层消失时,把先前记录的scrollTop
再次赋予页面。
此解决方案能够避免上述所有缺点。堪称完美。
(这个方案会导致主页面display:flex 的元素在弹框打开后消失)
css
body.dialog-open {
position: fixed;
width: 100%;
}
javascript
(function(){
var scrollTop = 0;
// 显示弹出层
open.onclick = function(){
// 在弹出层显示之前,记录当前的滚动位置
scrollTop = getScrollTop();
// 使body脱离文档流
document.body.classList.add('dialog-open');
// 把脱离文档流的body拉上去!否则页面会回到顶部!
document.body.style.top = -scrollTop + 'px';
mask.style.display = 'block';
}
// 隐藏弹出层
close.onclick = function(){
mask.style.display = 'none';
// body又回到了文档流中(我胡汉三又回来啦!)
document.body.classList.remove('dialog-open');
// 滚回到老地方
to(scrollTop);
}
function to(scrollTop){
document.body.scrollTop = document.documentElement.scrollTop = scrollTop;
}
function getScrollTop(){
return document.body.scrollTop || document.documentElement.scrollTop;
}
}());
解决滚动穿透的2个工具方法:
function fixedBody(){
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
document.body.style.cssText += 'position:fixed;top:-'+scrollTop+'px;';
}
function looseBody() {
var body = document.body;
body.style.position = '';
var top = body.style.top;
document.body.scrollTop = document.documentElement.scrollTop = -parseInt(top);
body.style.top = '';
}
参考文章[http://www.cnblogs.com/sohighthesky/p/mobile-modal-scroll.html]