效果

参考:

Youtube – Create a Simple Popup Modal

Youtube – Create a Modal (Popup) with HTML/CSS and JavaScript

HTML – Native Dialog Modal

Boostrap Modal

Angular Material Dialog

重点

1. modal 就是一个 position: fixed 的大 overlay 黑影, 同时里面有居中的 content box.

2. modal 原本是 hide 起来的, 点击后 show 就可以了.

HTML

<body>
<button id="js-open-modal-btn" class="open-modal-btn">Open Modal</button>
<div id="js-modal" class="modal">
<div class="content">
<div class="header">
<h1>You are The Winner!</h1>
<button id="js-close-modal-btn" class="close-modal-btn"><i class="fa-solid fa-xmark"></i></button>
</div>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Repellat id, rem veniam ratione modi laboriosam consectetur vitae illum perspiciatis recusandae!</p>
</div>
</div>
</body>

modal 负责 backdrop 黑影

content 则是中间白色的内容区域

CSS Style

.open-modal-btn{
margin-top: 17rem;
margin-inline: auto;
display: block;
} .modal {
visibility: hidden; // show / hide control position: fixed; // 定位
inset: 0; // full viewport background-color: rgb(0 0 0 / 0.2); // backdrop color // 居中 content
display: flex;
justify-content: center;
align-items: center; .content {
padding: 2rem 3rem;
max-width: 1024px;
background-color: white; // 因为 modal 是透明黑, 所以这里要 set 回白色
box-shadow: 0 2px 4px rgb(0 0 0 / 0.2); // 影子 .header{
display: flex;
justify-content: space-between;
align-items: center; font-size: 3rem; .close-modal-btn {
background-color: white;
font-size: inherit;
color: black;
border-width: 0;
cursor: pointer;
}
} p{
margin-top: 2rem;
font-size: 2rem;
}
} &.show {
visibility: initial; // clear visibility to show
}
}

看注释的地方解释就可以了, 其它是点缀而已

JavaScript

const modal = document.querySelector<HTMLElement>('#js-modal')!;
const openModalBtn = document.querySelector<HTMLButtonElement>('#js-open-modal-btn')!;
const closeModalBtn = document.querySelector<HTMLButtonElement>('#js-close-modal-btn')!;
openModalBtn.addEventListener('click', () => {
modal.classList.add('show');
}); closeModalBtn.addEventListener('click', () => {
modal.classList.remove('show');
});

只是简单的点击 add class 而已

Body Scroll IOS Safari Problem

modal 开启后, 通常体验不允许 body scroll. 一般的做法是给 body overflow: hidden

但是这个在 Safari 有 bug. 目前 status 是说已经 fixed 了, 但是我没用最新的 safari 测试, 所以不确定.

解决方法是让 body position fixed, 然后修改它的 top 到当前的 scroll top.

下面是我封装的方法

// note: 来龙去脉
// safari 没有办法通过 overflow hide 去阻止 body scroll
// 所以只能把 body 定位变成没有 scroll
// 这个 safari 问题已经很多年的了
// tesla, angular, stackoverflow 也是用这个方案去破
// bootstrap 倒没有处理这个, 比较 noob
// refer:
// https://bugs.webkit.org/show_bug.cgi?id=153852
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block const showedModals: string[] = []; export function toggleModal(modalName: string): void {
showedModals.includes(modalName) ? closeModal(modalName) : openModal(modalName);
} export function openModal(modalName: string): void {
if (showedModals.length === 0) {
const currentScrollTop = (document.scrollingElement ?? document.documentElement).scrollTop;
document.body.style.position = 'fixed';
document.body.style.width = '100%';
document.body.style.top = `-${currentScrollTop}px`;
}
showedModals.push(modalName);
} export function closeModal(modalName: string): void {
if (!showedModals.includes(modalName)) {
throw new Error(`Showed modals doesn't contains modal name: ${modalName}`);
}
if (showedModals.length === 1) {
const recoveryScrollTop = Math.abs(parseFloat(document.body.style.top));
document.body.style.removeProperty('position');
document.body.style.removeProperty('width');
document.body.style.removeProperty('top');
(document.scrollingElement ?? document.documentElement).scrollTop = recoveryScrollTop;
}
const indexOf = showedModals.indexOf(modalName);
showedModals.splice(indexOf, 1);
}

Mobile Back Button Close Dialog

大家习惯按手机的 back button 来试图关闭 Modal,

其实这是一个不正确的操作. 因为 back 会直接跳去上一页而不是关闭 Modal.

为了防止这样的错误体验. 我们可以做一点手脚.

step 1: 在打开 Modal的同时 history.push 放入 query param ?modal="show" (这样之后就可以 back 了)

step 2: 把关闭的操作 改成 history.back (统一关闭的方式)

step 3: 监听 onpopstate, 一旦发生就关闭 Modal.

step 4: 如果用户 refresh 那我们需要在 page load 的时候把 ?modal=show 用 history.replace 移除掉

以上的方法思路只是 for 简单场景的. 如果有多层 modal 或者更复杂的情况就 cover 不了了.

JS 代码:

const modal = document.querySelector<HTMLElement>('#js-modal')!;
const openModalBtn = document.querySelector<HTMLButtonElement>('#js-open-modal-btn')!;
const closeModalBtn = document.querySelector<HTMLButtonElement>('#js-close-modal-btn')!; // 处理 page load
const { pathname, search, hash } = location;
const queryParams = new URLSearchParams(search);
if (queryParams.has('whatsAppDialog')) {
queryParams.delete('whatsAppDialog');
const newSearch = queryParams.toString() !== '' ? `?${queryParams.toString()}` : '';
history.replaceState(null, '', `${pathname}${newSearch}${hash}`);
} openModalBtn.addEventListener('click', () => {
modal.classList.add('show');
// pushState
const { pathname, search, hash } = location;
const params = new URLSearchParams(search);
params.set('whatsAppDialog', 'open');
history.pushState(null, '', `${pathname}?${params.toString()}${hash}`); // listen to 'back button'
window.addEventListener(
'popstate',
() => {
modal.classList.remove('show');
},
{ once: true }
);
}); closeModalBtn.addEventListener('click', () => {
history.back(); // back
});

另外, 未来或许可以用 Navigation API 实现, 可能会更方便. 以后才研究. 毕竟现在许多 browser 还不支持.

其它没有提到的

1. backdrop click, Keyboard Esc 关闭.

2. show 的 animation, backdrop fadein, content scale in

3. z-index 问题. 要确保 z-index 够高最好是把 modal 放到 body 最下方 (Angular Material 就这么做的)

但放出去后要注意 CSS Style 哦. element 结构在外面了就不可以 depend on ancestor 了.

CSS & JS Effect – Dialog Modal的更多相关文章

  1. [转]jQuery UI Dialog Modal Popup Yes No Confirm example in ASP.Net

    本文转自:http://www.aspsnippets.com/Articles/jQuery-UI-Dialog-Modal-Popup-Yes-No-Confirm-example-in-ASPN ...

  2. HTML/CSS/JS编码规范

    最近整理了一份HTML/CSS/JS编码规范,供大家参考.目录:一.HTML编码规范二.CSS编码规范三.JS编码规范 一.HTML编码规范 1. img标签要写alt属性 根据W3C标准,img标签 ...

  3. CSS & JS 制作滚动幻灯片

    ==================纯CSS方式==================== <!DOCTYPE html> <html> <head> <met ...

  4. 【转】Maven Jetty 插件的问题(css/js等目录死锁)的解决

    Maven Jetty 插件的问题(css/js等目录死锁,不能自动刷新)的解决:   1. 打开下面的目录:C:\Users\用户名\.m2\repository\org\eclipse\jetty ...

  5. Css Js Loader For Zencart

    Css Js Loader 描述:这个插件很早就出来了,可能知道人非常少 这个插件的功能是整合所有的网站的CSS和JS内容到一个文件里边. 因为CSS和JS文件到了一个文件,加快了程序的运行 在配合其 ...

  6. 购物车数字加减按钮HTML+CSS+JS(有需要嫌麻烦的小伙伴拿走不谢)

    之前在写详情页的时候,如下图 因为自己嫌麻烦,就去看其他网站是怎么写的,想直接拿来用,后来看来看去觉得写得很麻烦,于是最后还是决定自己写,附上HTML+CSS+JS代码,一条龙一站式贴心服务2333 ...

  7. vs合并压缩css,js插件——Bundler & Minifier

    之前做了一个大转盘的抽奖活动,因为比较火,部分用户反馈看不到页面的情况,我怀疑js加载请求过慢导致,所以今天针对之前的一个页面进行调试优化. 首先想到的是对页面的js和css进行压缩优化,百度了下vs ...

  8. nginx资源定向 css js路径问题

    今天玩玩项目,学学nginx发现还不错,速度还可以,但是CSS JS确无法使用,原来Iginx配置时需要对不同类型的文件配置规则,真是很郁闷,不过想想也还是很有道理.闲暇之际,把配置贴上来.#user ...

  9. IIS7的集成模式下如何让自定义的HttpModule不处理静态文件(.html .css .js .jpeg等)请求

    今天将开发好的ASP.NET站点部署到客户的服务器上后,发现了一个非常头疼的问题,那么就是IIS7的应用程序池是集成模式的话,ASP.NET项目中自定义的HttpModule会处理静态文件(.html ...

  10. 网站加载css/js/img等静态文件失败

    网站加载css/js/img等静态文件失败,报网站http服务器内部500错误.而服务器中静态文件存在且权限正常. 从浏览器中直接访问文件,出来乱码.这种问题原因在于iis中该网站mime配置报错,不 ...

随机推荐

  1. 部分解决 | ocrmypdf对中文pdf进行ocr识别后存在多余空格

    1.问题 ocrmypdf安装采用的是在windows安装方法具体看 https://media.readthedocs.org/pdf/ocrmypdf/latest/ocrmypdf.pdf 由于 ...

  2. Mysql-explain之Using temporary和Using filesort解决方案

    第一条语句 explainselect * from tb_wm_shop where is_delete != 1 and is_authentication = 1 ORDER BY create ...

  3. BS架构和CS架构应用

    概述     B/S结构即浏览器和服务器结构.它是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构.在这种结构下,用户工作界面是通过WWW浏览器来实现,极少部分事务逻辑在前端(Br ...

  4. Python 正则表达式实战之Java日志解析

    需求描述 基于生产监控告警需求,需要对Java日志进行解析,提取相关信息,作为告警通知消息的内容部分. 提取思路 具体怎么提取,提取哪些内容呢?这里笔者分析了大量不同形态的生产日志,最后总结出4种形态 ...

  5. PHP 高性能框架 Workerman 凭什么能硬刚 Swoole ?

    大家好,我是码农先森. 一次偶然看到了国外某机构针对 PHP 周边生态框架及扩展的性能测试排行榜,看到 Workerman 竟遥遥领先 Swoole.在我们 PHP 程序员现有的认知里,Swoole ...

  6. Fiddler篡改请求和响应数据

    Fiddler标记断点后,我们可以通过篡改请求或响应数据,来模拟客户端请求和服务器响应. 一.打断点的方式 1.1 工具栏设置断点 工具栏勾选断点类型进行断点,路径:Rules->Automat ...

  7. python画图报错:OSError: 'seaborn-whitegrid' is not a valid package style

    解决方法: https://stackoverflow.com/questions/78019854/matplotlib-seaborn-whitegrid-is-not-a-valid-packa ...

  8. "观察者" 网站上不错的对社会问题进行思考的文章--------------- 分享

    原文地址:      https://www.guancha.cn/weichengling 在网上无意中到了下面的文章,对社会热点问题有较为全面的思考,感觉不错,分享一下. ------------ ...

  9. 【转载】 AI助力神经科学:DeepMind 复现大脑空间导航方式

    原文地址: https://baijiahao.baidu.com/s?id=1600279012514462353&wfr=spider&for=pc =============== ...

  10. 关于mysql配置文件中jdbc url 的记录

    版本不同 url不同 大同小异 基本就是不同参数配置的区别 maven 仓库地址 https://mvnrepository.com/artifact/mysql/mysql-connector-ja ...