滚动穿透

滚动穿透.gif

问题描述

在移动端 WEB 开发的时候(小程序也雷同),如上录屏所示,如果页面超过一屏高度出现滚动条时,在 fixed 定位的弹窗遮罩层上进行滑动,它下面的内容也会跟着一起滚动,看起来好像事件穿透到下面的DOM元素上一样,我们姑且称之为滚动穿透。

问题原因

能够猜想是文档(document)的滚动事件被触发了,如果能禁用滚动事件就好办了。

案例伪代码

<div class="btn">点击出现弹窗</div><div class="popup"><div class="popup-mask"></div><div class="popup-body popup-bottom"><div class="header">我是标题</div><div class="content"><div>0</div>        <div>1</div><div>...</div></div></div>
</div>
.popup-mask {background-color: rgba(0, 0, 0, 0.5);position: fixed;z-index: 998;top: 0;bottom: 0;left: 0;right: 0;
}.popup-body {padding: 0 50px 40px;background-color: #fff;position: fixed;z-index: 999;
}

✅ 解决方案A (touch-action)

默认情况下,平移(滚动)和缩放手势由浏览器专门处理,但是可以通过 CSS 特性 touch-action 来改变触摸手势的行为。摘取几个 touch-action 的值如下。

描述
auto 启用浏览器处理所有平移和缩放手势。
none 禁用浏览器处理所有平移和缩放手势。
manipulation 启用平移和缩放手势,但禁用其他非标准手势,例如双击缩放。
pinch-zoom 启用页面的多指平移和缩放。

于是在 popup 元素上设置该属性,禁用元素(及其不可滚动的后代)上的所有手势就可以解决该问题了。

.popup {touch-action: none;
}

Note: [无障碍设计] 阻止页面缩放可能会影响视力不佳的人阅读和理解页面内容,不过小程序本身好像就不可以缩放!

✅ 解决方案B (event.preventDefault)

来自 W3C 的一个标准。

描述.jpg

大意是说,在 touchstart 和 touchmove 事件中调用 preventDefault 方法可以阻止任何关联事件的默认行为,包括鼠标事件和滚动。

因此我们可以这样处理。
Step 1、监听弹窗最外层元素(popup)的 touchmove 事件并阻止默认行为来禁用所有滚动(包括弹窗内部的滚动元素)。
Step 2、释放弹窗内的滚动元素,允许其滚动:同样监听 touchmove 事件,但是阻止该滚动元素的冒泡行为(stopPropagation),使得在滚动的时候最外层元素(popup)无法接收到 touchmove 事件。

const popup = document.querySelector('.popup')
const scrollBox = document.querySelector('.content')popup.addEventListener('touchmove', (e) => {// Step 1: 阻止默认事件e.preventDefault()
})scrollBox.addEventListener('touchmove', (e) => {// Step 2: 阻止冒泡e.stopPropagation()
})

滚动溢出

滚动溢出.gif

问题描述

如上录屏所示,弹窗内也含有滚动元素,在滚动元素滚到底部或顶部时,再往下或往上滚动,也会触发页面的滚动,这种现象称之为滚动链(scroll chaining), 但是感觉滚动溢出(overscroll)这个名字更言辞达意。

❌ 解决方案A (overscroll-behavior)

overscroll-behavior 是 CSS 的一个特性,允许控制浏览器滚动到边界的表现,它有如下几个值。

描述
auto 默认效果,元素的滚动可以传播到祖先元素。
contain 阻止滚动链,滚动不会传播到祖先元素,但是会显示节点自身的局部效果。例如 Android 上过度滚动的发光效果或 iOS 上的橡皮筋效果。
none 与 contain 相同,但是会阻止自身的过度效果。

所以可以这样解决问题:

.content {overscroll-behavior: none;
}

简洁干净高性能,不过 Safari 全系不支持,兼容性如下,有没有感觉 Safari 就是现代版的 IE(偶然听路人说的)!

✅ 解决方案B (event.preventDefault)

借用 event.preventDefault 的能力,当组件滚动到底部或顶部时,通过调用 event.preventDefault 阻止所有滚动,从而页面滚动也不会触发了,而在滚动之间则不做处理。

let initialPageY = 0scrollBox.addEventListener('touchstart', (e) => {initialPageY = e.changedTouches[0].pageY
})scrollBox.addEventListener('touchmove', (e) => {const deltaY = e.changedTouches[0].pageY - initialPageY// 禁止向上滚动溢出if (e.cancelable && deltaY > 0 && scrollBox.scrollTop <= 0) {e.preventDefault()}// 禁止向下滚动溢出if (e.cancelable &&deltaY < 0 && scrollBox.scrollTop + scrollBox.clientHeight >= scrollBox.scrollHeight) {e.preventDefault()}
})

解决方案完整 Demo

https://github.com/Barrior/ca...

关于本文

作者:Barrior

https://segmentfault.com/a/1190000040675446

最后不要忘了点赞呦!
祝 2022 年暴富!暴美!暴瘦!

移动端滚动穿透与滚动溢出解决方案相关推荐

  1. 移动端滚动穿透的6种解决方案

    移动端滚动穿透的6种解决方案 参考文章: (1)移动端滚动穿透的6种解决方案 (2)https://www.cnblogs.com/bigkuan/p/11977674.html 备忘一下.

  2. datagrid底部显示水平滚动_滚动穿透问题探索

    在移动端开发中,模态(Modal)弹窗可以说是非常之常见了,作为正在看这篇文章的你,可能写过基于Vue或者小程序的统一弹窗Modal组件:可能处理过定宽高或者不定宽高的情况等,看起来一个小小的模态框其 ...

  3. 移动端滚动穿透问题完美解决方案

    移动端滚动穿透问题完美解决方案 参考文章: (1)移动端滚动穿透问题完美解决方案 (2)https://www.cnblogs.com/yaiza/p/11384130.html 备忘一下.

  4. 移动端页面滚动穿透问题解决方案

    移动端页面滚动穿透问题解决方案 参考文章: (1)移动端页面滚动穿透问题解决方案 (2)https://www.cnblogs.com/GeniusLyzh/p/5808446.html 备忘一下.

  5. 页面无法滚动_【前端词典】滚动穿透问题的解决方案

    点击上方"前端真好玩",喜欢他就关注他 听说,看恺哥的文章会上瘾 背景 产品有三宝,弹窗,浮层加引导: 设计有三宝,透明,阴影加圆角: 运营有三宝,短信,推送加红包: 程序员有一宝 ...

  6. 关于移动端滚动穿透问题的解决

    关于移动端滚动穿透问题的解决 移动端滚动穿透问题:在移动端进行fixed弹窗的时候,在弹窗上滑动会导致下层页面跟着滚动,影响用户体验,这种现象称为'滚动穿透'. 三种解决办法中,视需求选择解决办法: ...

  7. 移动页面滚动穿透解决方案(荐)

    为什么80%的码农都做不了架构师?>>>    移动页面滚动穿透解决方法目前有多种解决方案,我介绍下几种方案: 解决方案1:阻止冒泡. //关键代码 $(".sliders ...

  8. js - 移动端的超出滚动功能,附带滚动条,可解决弹层中滚动穿透问题。

    背景: 弹层里边有可滚动区域时,在移动端的坑我就不多说了. 找了很多解决滚动穿透的方案,最终都不能完美解决. 一气之下自己js撸了一个. 效果图: 原理: 1.解决滚动穿透:通过给弹层绑定touchm ...

  9. 弹层蒙版(mask),ios滚动穿透,我们项目的解决方案

    问题描述 项目开发遇到一个ios独有的问题,在wkwebview中稳定复现 问题: 弹出一个蒙版,当在蒙版上面滑动的时候蒙版后面的内容滚动了 这当然是ios的bug,但是经过我们测试iphone7也会 ...

最新文章

  1. 服务器如何删除所有磁盘信息,关于怎样删除EFI分区,简单省事,很多换下来的硬盘都有这个分区...
  2. 强监管下 协议支付会是互金平台救命稻草?(协议支付是代扣协议的升级版)
  3. mfc CString 转 char *
  4. 韦东山驱动视频笔记——3.字符设备驱动程序之poll机制
  5. 怎样玩转千万级别的数据
  6. 结合使用slf4j和Logback教程
  7. find、grep,which、whereis
  8. 这50个思维方法,深刻改变了我的人生
  9. 如何用iMazing导出苹果手机短信(彩信)
  10. 从客户端(content=span class=Apple-s...)中检测到有潜在危险的 Request.Form 值。
  11. 二分搜索(Binary Search)
  12. 清华大学王行言教授DELPHI程序设计在线学习
  13. telnet直接登录POP3
  14. 2014传智播客ios第4期基础班+就业班
  15. 苏宁小店门店数量一年锐减428家 张近东之子张康阳为实控人
  16. 关于网络存储技术和存储的协议
  17. 吴恩达机器学习ex1——通过人口预测小摊经济状况
  18. Flutter CircularProgressIndicator进度指示器/Loading
  19. STM32L0系列之【工程开始】
  20. MVC4 过滤器学习

热门文章

  1. 徐无忌MySQL笔记:乐观锁VS悲观锁
  2. 4个步骤,搭建接口测试自动化框架
  3. 买外链要多少钱?外链要去哪里买?
  4. Rasa课程、Rasa培训、Rasa面试、Rasa实战系列之 Language Agnostic BERT
  5. Web.config详解+asp.net优化
  6. 成年人的100个心酸瞬间:那些看似光鲜亮丽职业的背后......
  7. PS的png图片锁定不能解锁时
  8. 最全的linux基础学习视频
  9. AIX5.3上使用smit installp 安装Python 3.5.2
  10. 开发运动App的好处有哪些?