Dialog 弹窗也有“花活”?针不戳~
冲浪,看到一个 API HTMLDialogElement.showModal() - Web APIs | MDN
想想一直以来用 UI 框架的组件用惯了,即使自己写 Dialog,也只会老一套,用 JS + CSS display 属性来控制弹窗的显示和隐藏。
现在竟然直接有 API 方法了,纯 JS 实现。
🎉HTMLDialogElement.showModal()
掘了,一点 CSS 不带:
当然,有一点 CSS 不带的 Dialog 弹窗,相应的,也就有一点 JS 不带的纯 CSS 实现了~
🎉用 :target - CSS: Cascading Style Sheets | MDN 也能实现窗口的打开和关闭:
到这,还不足以说明:Dialog 弹窗也有“花活”
称得上花活的是 CSS :modal 伪类属性。
它用来检测当前的弹框,这样避免了在 JS 中管理 CSS
用法:
dialog:modal {
scale: 2;
}
当出现弹框时,scale 赋值为 2
下面带来一个实战案例:
- HTML
<div class="warning-message">
:modal isn't supported in this browser :(
</div>
<dialog>
<p>I'm a Dialog</p>
<button>Close</button>
</dialog>
<div class="actions">
<button data-modal="true">Open Modal</button>
<button data-modal="false">Open Non-modal</button>
</div>
- CSS
layer demo {
dialog[open]:not(:modal) {
z-index: 2;
transform-style: preserve-3d;
}
dialog[open]:not(:modal):before {
content: "";
position: fixed;
height: 100vh;
width: 100vw;
top: 50%;
left: 50%;
background: hsl(0 0% 10% / 0.25);
transform: translate3d(-50%, -50%, -1px);
}
}
@layer base {
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
min-height: 100vh;
background: var(--gradient-3);
font-family: "Google Sans", sans-serif, system-ui;
}
.actions {
display: flex;
gap: var(--size-4);
}
dialog {
padding: var(--size-4);
gap: var(--size-2);
background: var(--surface-1);
}
dialog::backdrop {
background: hsl(0 0% 10% / 0.5);
}
dialog[open] {
display: grid;
}
.warning-message {
border: var(--size-1) solid var(--yellow-4);
padding: var(--size-4);
background: var(--gray-0);
position: fixed;
top: var(--size-4);
left: var(--size-4);
}
@supports (selector(:modal)) {
.warning-message {
display: none;
}
}
}
- JS
const BUTTONS = document.querySelectorAll("button");
const DIALOG = document.querySelector("dialog");
BUTTONS.forEach((BUTTON) => {
BUTTON.addEventListener("click", (e) => {
let modalStyle;
switch (BUTTON.getAttribute("data-modal")) {
case "true":
modalStyle = "showModal";
break;
case "false":
modalStyle = "show";
break;
default:
modalStyle = "close";
}
DIALOG[modalStyle]();
});
});
我们可以检测出非 :modal 的 dialog,为了以示区别,再加一个伪类 :before,做点不一样的样式出来。
你可以在这里测试:Is it :modal?
需要特别强调的是,它是一个比较新的属性,浏览器兼容目前还比较差,不过我们可以给予适当关注。
其实,这种思想是非常好的:即避免在 JS 中操作更多的样式。你可以去取值,去共享 CSS 的能力,但是不要去改值,不然样式问题就一团糟了~
细看以上代码还有很多有趣的用法,比如:
@layer ...
@supports (selector(:modal)) {
.warning-message {
display: none;
}
}
你知道它们都是干什么用的吗?
@layer - CSS: Cascading Style Sheets | MDN
@supports - CSS: Cascading Style Sheets | MDN
把代码 clone 在线运行试试,进一寸有一寸的欢喜~
转载自:https://juejin.cn/post/7169724088938659853