在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>
效果如下:
将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;
}
}
这样点击话,就可以区分出来啦😉
然后判断一下,大功告成:
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;
}
完美解决问题😁,并且显示跟隐藏都有过渡效果了。关于上述隐藏元素的方法,后面会专门出一篇文章详解。
大家有没有发现,遮罩
背景并没有过渡效果,只是dialog
元素本身有。
我尝试写如下代码:
dialog::backdrop {
opacity: 1;
transition: opacity 10s ease;
}
dialog:not([open])::backdrop {
opacity: 0;
}
发现并没有效果,欢迎各位在评论补充
或者纠正
😘
浏览器兼容表
放心,这里有官方的polyfill
:
最后
如果你觉得这篇文章不错,请别忘记点个赞
跟关注
哦~😊
交流
微信公众号「前端宇宙情报局」
,将不定时更新最新、实用的前端
技巧/技术性文章,对了偶尔还会有互联网
中的趣事趣闻🍻
关注公众号,回复"1"
加入微信学习群,一起学习、一起交流、一起摸鱼🌊
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。