在做H5开发时,移动很多场景下都需要弹窗。端阻
当出现弹窗时,止弹大部分场景下是窗下层页期望弹窗下层页面不能被滑动的。
当然也不期望弹窗被滑动
近期肝页面又碰到了这个问题
下面介绍几种最常用的面被方式,以及一些边界情况与应对策略。滑动
流传最广的介绍方式就是 给元素设置 overflow:hidden
给body设置,就能达到阻止页面滑动的移动目的
document.body.style.overflow = hidden
document.body.style.overflow = visible大部分情况下这个是能有效果的
但在部分机器上,这个是端阻不生效的:
还有一种情况如下,页面部分元素有局部滑动
</body>当前情况给body设置 overflow:hidden依旧是止弹无效果的
此时给弹窗加上遮罩如下,正常情况下,窗下层页下层元素就不会收到touchmove事件
</body>其中inset属性是源码下载面被left,top,right,bottom的简写
但在部分机型下,下层元素仍然会收到touchmove事件,滑动因此会跟着滑动
于是介绍需要祭出下面的方法
阻止触摸滑动事件touchmove的默认行为
const touchHandle = function(e) {
e.preventDefault()
}
// 弹窗的事件
{
onShow(){
document.body.addEventListener(touchmove, preventDefault, {
passive: false,
});
},
onHide(){
document.body.removeEventListener(touchmove, preventDefault);
}
}在弹窗打开时直接阻止目标元素的滑动事件的默认行为
弹窗内容是不可滑动的话,那么这种方法是移动最省事高效的
如果弹窗中有可滑动的内容,且滑动的内容比较复杂
那么通过touchmove去细力度的控制阻止滑动事件时就很麻烦
还有一种常用的就是position:fixed
在弹窗打开时,将目标元素进行固定,在关闭时恢复
由于定位会改变元素在页面上的位置,站群服务器所以需要在fixed前记录元素的位置
取消fixed之后将元素又滚动到原来的位置
// 弹窗的事件
{
onShow(){
document.body.style.top = `${
document.body.getClientRects()[0].top
}px`;
document.body.style.position = fixed;
document.body.style.left = 0;
document.body.style.right = 0;
},
onHide(){
document.body.style.position = visible;
window.scrollTo(
0,
Math.abs(+document.body.style.top.replace(px, ))
);
}
}这个也是碰巧发现的,在iOS低端机将上述方式都尝试后
仍发现一个问题,现象如下(TODO:补图)
下层页面不会被滑动了,但遮罩和弹窗整体还能被下拉
弹窗是一个下拉列表弹窗,其出现的位置需要动态的计算,如下结构
</body>最终发现是由于style与class设置的样式在这个机型上展示虽然一致
但实际交互起来的表现却不一致
修复后的html结构如下,在元素里插入了一个style标签,使用class选择器与!important重载这个距离的样式
.dialog{
top:88px !important;
}
</body>代码如下
{
onShow(){
setTimeout(() => {
const dialogEl = document.querySelector
if (!dialogEl) {
return
}
const style = document.createElement(style)
style.textContent = `
.dialog{
top:${ dialogEl.style.top} !important;
}
`
dialogEl.append(style)
}, 200)
}
}非常令人迷惑的一个操作,但就是解决了问题
针对移动端弹窗下层页面可被滑动的异常场景
本文介绍了4种常见解决方法,香港云服务器与1种"谜之操作"