冲浪,看到一个 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 在线运行试试,进一寸有一寸的欢喜~