在 html5 中, 新增了很多语义化的标签. 如 footer,header 之类的, 今天的主角是 dialog 标签
顾名思义, 就是用来定义对话框的. 目前只有 Chrome 和 Safari 支持该标签, 所以用的不多, 不过确实挺好用的
别担心, 有官方的 polyfill.
使用方法
1. 基础的用法
<dialog open > 我是一个对话框 </dialog>
可以 open 属性控制 dialog 是否显示, 效果如下:
看看浏览器渲染的默认样式:
是挺丑的, 而且默认还不是全屏居中, 有透明遮罩
2. 使用 JS API
当然, 也可以用 JS 来控制元素的显示跟隐藏.
常用的有三个方法:
名称 | 说明 |
---|---|
show | 显示 dialog 元素(跟 open 属性控制一样) |
showModal | 显示 dialog 元素,并且全屏居中,并带有黑色透明遮罩 |
close | 隐藏 dialog 元素 |
简单的用法:
- <dialog>
- <p > 我是一个对话框 </p>
- <button onclick="hideDialog()"> 隐藏对话框 </button>
- </dialog>
- <button onclick="showDialog()"> 显示对话框 </button>
- <script>
- let dialog = document.querySelector("dialog");
- // 显示对话框
- function showDialog() {
- dialog.show();
- }
- // 隐藏对话框
- function hideDialog() {
- dialog.close();
- }
- </script>
web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法 (详细的前端项目实战教学视频)
效果如下:
将 dialog.show() 改成 dialog.showModal(), 看看效果:
就像上面介绍所说的 "全屏居中, 并带有黑色透明遮罩", 看起来还不错
默认样式倒没变, 只是多加了一个::backdrop 伪元素 (透明遮罩):
3. 修改背景色
想改背景颜色可以直接覆盖掉样式:
- dialog::backdrop {
- background: linear-gradient(45deg, black, transparent);
- }
效果如下:
多个对话框
如果同时出现多个对话框, 会根据调用的先后顺序叠加上去.
假设布局如下 (省略 JS 代码, 因为大同小异):
- <dialog>
- <p > 我是第一个对话框 </p>
- <button onclick="hideDialog1()"> 隐藏对话框 </button>
- <button onclick="showDialog2()"> 显示第二个对话框 </button>
- </dialog>
- <dialog>
- <p > 我是第二个对话框 </p>
- <p > 我是第二个对话框 </p>
- <button onclick="hideDialog2()"> 隐藏对话框 </button>
- </dialog>
- <button onclick="showDialog1()"> 显示第一个对话框 </button>
效果如下:
既然是叠加, 那么背景色一定会叠加 (同时存在多个 dialog 元素), 这是必然的
dialog 本身的样式也可以修改, 直接覆盖即可:
- dialog {
- border: none;
- border-radius: 8px;
- }
效果如下:
点击遮罩关闭对话框
目前并没有参数 / 属性可以设置 "点击遮罩进行关闭对话框", 但是这个需求很常见不是吗?
思考了一会, 那就自己实现一个吧, 其实给 dialog 添加一个 click 事件, 当点击的目标为遮罩的时候, 然后把自己隐藏掉就行了.
- dialog.onclick = function(event) {
- console.log(event.target);
- };
但是事实却没那么顺利:
无论你点哪里, 目标元素都是 dialog, 但是, 有一个非常机智的方法.
我把结构变成如下:
- <dialog>
- <div class="content">
- // 这是内容...
- </div>
- </dialog>
然后把 dialog 默认的 padding 转移到. content 上!
- dialog {
- padding: 0;
- .content {
- padding: 1rem;
- }
- }
Web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法 (详细的前端项目实战教学视频)
这样点击话, 就可以区分出来啦
然后判断一下, 大功告成:
- dialog.onclick = function(event) {
- if (event.target.tagName.toLowerCase() == "dialog") this.close();
- };
效果如下:
把 "可点击遮罩关闭" 配置化
我们约定一个属性 closeByMask, 若标签上存在该属性, 则可以进行点击关闭:
- <dialog closeByMask>
- </dialog>
- <dialog closeByMask>
- </dialog>
然后添加以下脚本即可:
- document.querySelectorAll("dialog[closeByMask]").forEach(dialog => {
- dialog.onclick = function(event) {
- if(event.target.tagName.toLowerCase() == "dialog") this.close();
- }
- });
然后不管你怎么嵌套都行啦
假如两个 dialog 都存在 closeByMask 属性:
假如第二个 dialog 才存在 closeByMask 属性:
如何加过渡动画
1. 使用 animation
- dialog {
- animation: slideDown 0.2s ease;
- }
- @keyframes slideDown {
- from {
- transform: translateY(-100px);
- }
- to {
- transform: translateY(0);
- }
- }
效果如下:
缺点: 关闭的时候没有动画
2. 使用 transition
没有 open 属性的 dialog 元素是被默认设置成 display: none 的.
众所周知 transition 是不支持 display 过渡的
所以, 我们得把 display: none 换成 opacity: 0 就可以支持过渡啦
- dialog {
- transition: opacity 0.4s ease;
- opacity: 1;
- }
- dialog:not([open]) {
- display: block;
- opacity: 0;
- }
效果如下:
但是 opacity 只是设置透明度为而已, 实际上 dialog 元素还是存在的, 如果 dialog 里面绑定了点击事件, 一样会执行, 即使你看不见它
比如这样:
不要慌嘻嘻, 我们不是还有 visibility 属性吗哈哈哈, 所以 CSS 代码改成如下:
- dialog:not([open]) {
- display: block;
- opacity: 0;
- visibility: hidden;
- }
Web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法 (详细的前端项目实战教学视频)
完美解决问题, 并且显示跟隐藏都有过渡效果了. 关于上述隐藏元素的方法, 后面会专门出一篇文章详解.
大家有没有发现, 遮罩背景并没有过渡效果, 只是 dialog 元素本身有.
我尝试写如下代码:
- dialog::backdrop {
- opacity: 1;
- transition: opacity 10s ease;
- }
- dialog:not([open])::backdrop {
- opacity: 0;
- }
发现并没有效果, 欢迎各位在评论补充或者纠正
浏览器兼容表
放心, 这里有官方的 polyfill:
dialog-polyfill
最后
如果你觉得这篇文章不错, 请别忘记点个赞跟关注哦~
如果你喜欢这篇文章, 请别忘记点个赞或者关注
来源: http://www.jianshu.com/p/eaa9708b2867