当前位置: 首页 > 编程日记 > 正文

禁止蒙层底部页面跟随滚动

场景概述

弹窗是一种常见的交互方式,而蒙层是弹窗必不可少的元素,用于隔断页面与弹窗区块,暂时阻断页面的交互。但是,在蒙层元素中滑动的时候,滑到内容的尽头时,再继续滑动,蒙层底部的页面会开始滚动,显然这不是我们想要的效果,因此需要阻止这种行为。

那么,如何阻止呢?请看以下分析:

方案分析

方案一

  • 打开蒙层时,给body添加样式:
overflow: hidden;
height: 100%;

在某些机型下,你可能还需要给根节点添加样式:

overflow: hidden;
  • 关闭蒙层时,移除以上样式。

优点:
简单方便,只需添加css样式,没有复杂的逻辑。

缺点:
兼容性不好,适用于pc,移动端就尴尬了。
部分安卓机型以及safari中,无法无法阻止底部页面滚动。

如果需要应用于移动端,那么你可能需要方案二。

方案二

就是利用移动端的touch事件,来阻止默认行为(这里可以理解为页面滚动就是默认行为)。

// node为蒙层容器dom节点
node.addEventListener('touchstart', e => {e.preventDefault()
}, false)

简单粗暴,滚动时底部页面也无法动弹了。假如你的蒙层内容不会有滚动条,那么上述方法prefect。

但是,最怕空气突然安静,假如蒙层内容有滚动条的话,那么它再也无法动弹了。因此我们需要写一些js逻辑来判断要不要阻止默认行为,复杂程度明显增加。

具体思路:判定蒙层内容是否滚动到尽头,是则阻止默认行为,反之任它横行。


Tip:这里我发现了一个小技巧,可以省略不少代码。在一次滑动中,若蒙层内容可以滚动,则蒙层内容滚动,过程中即使蒙层内容已滚至尽头,只要不松手(可以理解为touchend事件触发前),继续滑动时页面内容不会滚动,此时若松手再继续滚动,则页面内容会滚动。利用这一个小技巧,我们可以精简优化我们的代码逻辑。

示例代码如下:

<body><div class="page"><!-- 这里多添加一些,直至出现滚动条 --><p>页面</p><p>页面</p><button class="btn">打开蒙层</button><p>页面</p></div><div class="container"><div class="layer"></div><div class="content"><!-- 这里多添加一些,直至出现滚动条 --><p>蒙层</p><p>蒙层</p><p>蒙层</p></div></div>
</body>
body {margin: 0;padding: 20px;
}.btn {border: none;outline: none;font-size: inherit;border-radius: 4px;padding: 1em;width: 100%;margin: 1em 0;color: #fff;background-color: #ff5777;
}.container {position: fixed;top: 0;left: 0;bottom: 0;right: 0;z-index: 1001;display: none;
}.layer {position: absolute;top: 0;left: 0;bottom: 0;right: 0;z-index: 1;background-color: rgba(0, 0, 0, .3);
}.content {position: absolute;bottom: 0;left: 0;right: 0;height: 50%;z-index: 2;background-color: #f6f6f6;overflow-y: auto;
}
const btnNode = document.querySelector('.btn')
const containerNode = document.querySelector('.container')
const layerNode = document.querySelector('.layer')
const contentNode = document.querySelector('.content')
let startY = 0 // 记录开始滑动的坐标,用于判断滑动方向
let status = 0 // 0:未开始,1:已开始,2:滑动中// 打开蒙层
btnNode.addEventListener('click', () => {containerNode.style.display = 'block'
}, false)// 蒙层部分始终阻止默认行为
layerNode.addEventListener('touchstart', e => {e.preventDefault()
}, false)// 核心部分
contentNode.addEventListener('touchstart', e => {status = 1startY = e.targetTouches[0].pageY
}, false)contentNode.addEventListener('touchmove', e => {// 判定一次就够了if (status !== 1) returnstatus = 2let t = e.target || e.srcElementlet py = e.targetTouches[0].pageYlet ch = t.clientHeight // 内容可视高度let sh = t.scrollHeight // 内容滚动高度let st = t.scrollTop // 当前滚动高度// 已经到头部尽头了还要向上滑动,阻止它if (st === 0 && startY < py) {e.preventDefault()}// 已经到低部尽头了还要向下滑动,阻止它if ((st === sh - ch) && startY > py) {e.preventDefault()}
}, false)contentNode.addEventListener('touchend', e => {status = 0
}, false)

问题虽然是解决了,但是回头来看,复杂程度和代码量明显增加了一个梯度。
本着简单方便的原则,我们是不是还可以探索其他的方案呢?

既然touch事件判定比较复杂,何不跳出这个框框,另辟蹊径,探索更加合适的方案。
于是,便有了我们的方案三。

方案三

来讲讲我的思路,既然我们要阻止页面滚动,那么何不将其固定在视窗(即position: fixed),这样它就无法滚动了,当蒙层关闭时再释放。
当然还有一些细节要考虑,将页面固定视窗后,内容会回头最顶端,这里我们需要记录一下,同步top值。

示例代码:

let bodyEl = document.body
let top = 0function stopBodyScroll (isFixed) {if (isFixed) {top = window.scrollYbodyEl.style.position = 'fixed'bodyEl.style.top = -top + 'px'} else {bodyEl.style.position = ''bodyEl.style.top = ''window.scrollTo(0, top) // 回到原先的top}
}

思考总结

  • 若应用场景是pc,推荐方案一,真的是不要太方便
  • 若应用场景是h5,你可以采用方案二,但是我建议你采用方案三
  • 若应用场景是全平台,那么方案三你不容错过

本文到这里也即将结束了,在这里我强烈推荐一下方案三,原因在于简单、方便、兼容性好,一次封装,永久受用。

相关文章:

squid日志文件太大,怎样处理?

Squid 默认的&#xff15;天会压缩一次, 在 /etc/logrotate.d/squid中有设置。如果你修改了日志的位置, 请修改 /etc/logrotate.d/squid /home/log/squid/access.log { weekly rotate 5 copytruncate compress notifempty missingok } /home…

安卓系列七(广播机制)

2019独角兽企业重金招聘Python工程师标准>>> 一、什么是广播接收者 广播接收者&#xff08;BroadcastReceiver&#xff09;用于接收广播Intent&#xff0c;广播Intent的发送是通过调用Context.sendBroadcast()、Context.sendOrderedBroadcast()来实现的。通常一个广…

第九代小冰惊喜登场,多端融合且琴棋书画样样精通

谈及智能助手&#xff0c;相信大家都不会漏过小冰这款具有划时代意义的产品。从最初的微软小冰到现在的第九代小冰&#xff0c;AI的技术在不断的演进&#xff0c;而小冰也从最初的贴心助手变成了如今琴棋书画样样精通的人工智能前沿技术载体。 北京时间2021年9月22日&#xff…

C++对象赋值的四种方式

1. 引用作为参数的方式传递. 1 GetObject(Object& obj) 2 { 3 obj.value value1; 4 } 特点: 在外部构造一个对象. 把该对象以引用的方式传递到函数中. 从而实现对该对象的改变, 该参数实质是一个[out]类型的参数, 而非[in]类型的参数. 这里的引用可以称为别名. 点评: …

金九银十,不要跳槽!

前言:又到了求职的金九银十的黄金月份&#xff0c;我相信有不少小伙伴已经摩拳擦掌的准备寻找下一份工作。就目前国内的面试模式来讲&#xff0c;在面试前积极的准备面试&#xff0c;复习整个 Java 知识体系将变得非常重要&#xff0c;可以很负责任地说一句&#xff0c;复习准备…

FreeMarker标签介绍

FreeMarker标签使用 一、FreeMarker模板文件主要有4个部分组成 1、文本&#xff0c;直接输出的部分 2、注释&#xff0c;即<#--...-->格式不会输出 3、插值&#xff08;Interpolation&#xff09;&#xff1a;即${..}或者#{..}格式的部分,将使用数据模型中的部分替代输…

让Squid 显示本地时间

Squid的Error messages 默认的时间显示的GMT时间&#xff0c;而非本地时间&#xff0c;这个有时候看着很别扭。 下面是修改方法&#xff0c;找到Squid的源文件src/errorpage.c 大概在60多行&#xff0c; { ERR_SQUID_SIGNATURE, "\n<BR clear\"all\">\n&…

linux mysql 命令 大全

linux mysql 命令 大全 1.linux下启动mysql的命令&#xff1a; mysqladmin start /ect/init.d/mysql start (前面为mysql的安装路径) 2.linux下重启mysql的命令&#xff1a; mysqladmin restart /ect/init.d/mysql restart (前面为mysql的安装路径) 3.linux下关闭mysql的…

助力5G行业应用扬帆启航,第二届5G毫米波产业高峰论坛圆满召开

当前&#xff0c;5G发展如火如荼&#xff0c;成为引领我国高质量发展的新引擎。5G要想进一步实现向千行百业拓展&#xff0c;离不开全频段的支持&#xff0c;推动5G毫米波发展成为各国共识。为进一步推进5G毫米波产业发展&#xff0c;释放5G全部潜能&#xff0c;助力5G行业应用…

Bootstrap3.x - 源代码分析

参照http://v3.bootcss.com/css/ 文档与源代码colors 比较全面定义总结有意义的颜色。所有uI要用的颜色&#xff0c;都先从已定义的读&#xff0c;这样保证样式的同一性&#xff0c;而且方便以后开发主题库。(建议想自己写css模块的&#xff0c;可以参考一下bootstrap里颜色定义…

清除Squid缓存的小工具

[ 2007-11-2 17:49 | by 张宴 ] 以前我写过一篇《清除指定squid缓存文件的脚本》&#xff0c;但在取URL时存在10%的错误率。如今找到一款老外的程序&#xff0c;可以批量清除某类URL的Squid缓存&#xff0c;支持正则表达式。下载网址&#xff1a;http://www.wa.apana.org.au/~d…

谷歌 AI 编舞师,连张艺兴最喜欢的 Krump 都不在话下

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 舞蹈一直是文化、仪式和庆祝活动的重要组成部分&#xff0c;也是一种自我表达的方式。今天&#xff0c;存在多种形式的舞蹈&#xff0c;从舞厅到迪斯科。然而&#xff0c;舞蹈是一种需要练习的艺术形…

Python 字典(Dictionary)

Python 字典(Dictionary)字典是另一种可变容器模型&#xff0c;且可存储任意类型对象。字典的每个键值(key>value)对用冒号(:)分割&#xff0c;每个对之间用逗号(,)分割&#xff0c;整个字典包括在花括号({})中 ,格式如下所示&#xff1a;d {key1 : value1, key2 : value2 …

Varnish Cache 3.0.0安装

https://www.varnish-cache.org/installation/redhat Installation on RedHat 先按需要的模块 在安装软件包之前首先看看主机上的 automake autoconf libtool ncurses-devel libxslt groff pcre-devel pkgconfig软件包是否已经安装 如果没有那么就要首先安装&#xff…

three.js绘制过程(二)

2019独角兽企业重金招聘Python工程师标准>>> 同一个场景中可以有多个摄像机&#xff0c;同一个屏幕缓冲区可以分块绘制不同的物体。 WeblGLRender 中autoClear 设定为false之后&#xff0c; 每次绘制不会清空缓冲区&#xff1b; setSize 设定canvas的大小 setViewpo…

AI 不可以作为专利认证发明人,“因为它不是人”

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 英格兰和威尔士上诉法院本周驳回了一名男子的请求&#xff0c;该男子要求法院承认他的人工智能系统为两项专利的发明者。 总部位于美国的 Imagination Engines 的创始人 Stephen Thaler 想要给智能机器…

使用工作集(Working Set)整理项目

Eclipse鼓励将不同的功能模块划分为独立的项目存在&#xff0c;这样不但结构清晰&#xff0c;组织起来还非常灵活&#xff0c;因为我们可以用feature对这些项目进行不同的组合&#xff0c;输出后得到具有不同功能的产品。 不过这样一来Package Explorer里的项目会以更快的速度增…

深入探讨Varnish缓存命中率

也许你还在为刚才动态内容获得7336.76 reqs/s的吞吐率感到振奋&#xff0c;等等&#xff0c;理想和现实是有差距的&#xff0c;你要忍受现实的残酷&#xff0c;别忘了&#xff0c;我们压力测试中的动态内容都处于全缓存情况下&#xff0c;也就是每次请求都命中缓存&#xff0c;…

网易有道词典笔 —— 73 岁“人类高质量”奶奶梅耶马斯克的中文学习之选

继埃隆马斯克发微博称7000年后英语将不复存在后&#xff0c;他的忠实粉丝&#xff0c;同时也是他的母亲——梅耶马斯克也正式开启了学习新语言行动&#xff0c;值得注意的是&#xff0c;梅耶的语种选择是中文。近日&#xff0c;埃隆马斯克的母亲——梅耶马斯克使用有道词典笔学…

Android类库打包方法探究

为什么80%的码农都做不了架构师&#xff1f;>>> 开发Android应用的时候&#xff0c;对于可用于多个应用的公用的部分&#xff0c;或是打算发布给第三方进行应用集成的部分&#xff0c;要把这部分打包成类库怎么做呢? 众所周知&#xff0c;Android应用使用ADT打包成…

大叔也说并行和串行`性能提升N倍(N由操作系统位数和cpu核数决定)

并行是.net4.5主打的技术&#xff0c;同时被封装到了System.Threading.Tasks命名空间下&#xff0c;对外提供了静态类Parallel&#xff0c;我们可以直接使用它的静态方法&#xff0c;它可以并行一个委托数组&#xff0c;或者一个IEnumerable的迭代&#xff0c;而今天主要通过一…

这7个开源技术,支撑起整个互联网时代

转载自 钛媒体 - 这7个开源技术&#xff0c;支撑起整个互联网时代 开源软件现在成为整个互联网时代的支撑技术&#xff0c;你可能已经无法离开由开源软件构建起来的网络世界了。下面我们就来看看一些最重要的开源技术。 为互联网而生的操作系统linux Linux是一款免费的操作系统…

WebDriver 识别反爬虫的原理和破解方法~

作者|志斌来源|python笔记有时候我们在爬取动态网页的时候&#xff0c;会借助渲染工具来进行爬取&#xff0c;这个“借助”实际上就是通过使用相应的浏览器驱动(即WebDriver)向浏览器发出命令。但是有时候使用浏览器驱动来爬取网页时&#xff0c;会遇到这种情况这时&#xff0c…

Linux下文件如果没有权限不能被Apache访问

通过 apache的网站 php和图片都可以显示 就是 Htm页面不行 报错 Forbidden You dont have permission to access /me/1.html on this server. 其实是权限设置问题 可以 到文件所在目录 使用命令查看权限 #ls -al 再使用chmod命令给予足够权限即可 #chmod 0644 文件名…

html标签的显示模式(块级标签,行内标签,行内块标签)(转)

html标签的显示模式&#xff08;块级标签&#xff0c;行内标签&#xff0c;行内块标签&#xff09; 今天讲课的时候&#xff0c;讲到了html中的标签的显示模式&#xff0c;大致分为块级标签和行内标签。那么初学者在刚使用标签的时候会发现有些属性在一些标签上不起作用&#x…

RT-thread内核之进程间通信

一、进程间通信机制 rt-thread操作系统的IPC&#xff08;Inter-Process Communication&#xff0c;进程间同步与通信&#xff09;包含有中断锁、调度器锁、信号量、互斥锁、事件、邮箱、消息队列。其中前5个主要表现为线程间同步&#xff0c;邮箱与消息队列表现为线程间通信。本…

Linux内核学习四库全书

关于内核学习我建议不要上来就读内核而是先了解内核的构成和特性&#xff0c;然后通过思考发现疑问这时再去读内核源码。即先了解概貌在读局部细节。而且内核分成好多部分&#xff0c;不要只是按照顺序去读&#xff0c;应该针对某一部分比如内存管理或进程管理横向读几本书&…

46W 奖金池等你来战!微众银行第三届金融科技高校技术大赛火热报名中!

青春是什么&#xff1f;张爱玲曾说过&#xff0c;青春是个奇形怪状的玩意儿&#xff0c;短短的身子偏偏拖了一个长长的尾巴&#xff0c;像翅膀一样的招摇着&#xff0c;久久不肯离去。对于你我而言&#xff0c;青春是什么&#xff1f;青春也许是大学里点点滴滴的记忆&#xff1…

spring cloud快速搭建

为什么80%的码农都做不了架构师&#xff1f;>>> 一&#xff1a;注册中心 服务提供者&#xff08;简单&#xff09; 注册中心本身就可以是服务提供者&#xff0c;如果有需求可以分开。 1&#xff1a;pom.xml <?xml version"1.0" encoding"UTF-8…

ubuntu操作系统下载

原文网址&#xff1a;http://www.cyberciti.biz/linux-news/download-ubuntu-14-4-cd-dvd-iso-images/ Download of the day: Ubuntu Linux 14.04 LTS CD / DVD ISO by NIXCRAFT on APRIL 17, 2014 5 COMMENTS LAST UPDATED APRIL 17, 2014 in LINUX NEWS, OPEN SOURCE Ubuntu…