Better warnings, modals, and confirmations with the <dialog> element
Updated June 2, 2023: dialog
now enjoys native support in most major browsers. Use the polyfill if you wish to support older browsers. I also recommend replacing existing modals with the native dialog
element.
Updated January 6, 2020: Alas, the dialog
element presents some accessbility challenges. You'll need to use ARIA carefully to enhance the dialog
element until browsers add native and consistent support.
The World Wide Web Consortium (W3C) released HTML 5.2 as a recommendation at the end of 2017. One of the features it added to its version of the HTML5 specification is the dialog
element. Think of dialog
as the modal element you always wanted, and no longer have to build.
Now, it's slightly misleading to call dialog
a new feature of HTML5. It's been part of the Web Hypertext Application Technology Working Group (WHATWG) version of the specification for several years now.1 Chrome added experimental support in version 32, which was released in 2014. Full support arrived a few months later. (Opera, which shares much of the same code base as Chrome, added support in version 19.)
For several years, Chrome, Opera (and other Blink/Chromium-based user agents) were the only browsers to support the dialog
element. In 2022, however, Firefox added full support for dialog
after a several years of including it as an experimental feature. But that changed last year when Firefox added experimental support for dialog
behind a flag (to enable it, change dom.dialog_element.enabled
to true
in about:config
).
Now that the W3C has included it in its HTML 5.2 recommendation, Now that dialog
enjoys support in most major browsers, it's a good time to learn how to use it. There's a polyfill available for older browsers that lack support, but it has some limitations.
Create your first dialog
Creating a dialog is super simple.
<dialog>Hi. I am a dialog.</dialog>
You can place this anywhere in your HTML document.
Dialog elements are closed and invisible by default. To open our dialog
, we'll need to add an open
attribute.
<dialog open>Hi. I am a dialog.</dialog>
You can also open dialogs using one of the element's DOM scripting methods. dialog
has three methods — two that open the modal, and one that closes it.
show()
: Opens the modal.showModal()
: Opens the modal, and makes it the top-most dialog.close()
: Closes the modal.
I'm sure there's a long back story replete with a flame war that explains why we have both the show()
and showModal()
methods. That said, there are subtle but important differences in how they operate.
showModal()
honors theautofocus
attribute, whileshow()
may not.Chrome and Opera renderDialogs opened usingshowModal()
showModal()
render with a backdrop. Those opened usingshow()
do not.- Dialogs opened with
showModal()
can be closed with theEsc
key. Those opened withshow()
cannot(and typically don't need to be).
The following demo illustrates the difference.
I've also tweaked the user-agent styling for the dialog
element in this demo. The default style is kind of ugly.
You can style showModal()
backdrop using the ::backdrop
pseudo-element. Note that if you use the polyfill, you'll need to use dialog + .backdrop
as a selector for stylying the backdrop.
This is one place, by the way, where the W3C and WHATWG specifications diverge. In the W3C version of the specification, show()
and showModal()
accept an optional anchor point argument. In the WHATWG version, neither method accepts an argument. Since browser implementations are still emerging, that could have changed between the time I wrote and published this post and the time you began reading it.
Using the polyfill
Download the dialog-element polyfill directly from GitHub. Or use your favorite JavaScript package manager (e.g. npm install dialog-polyfill
).
Link dialog-polyfill.css from your document head
. Add dialog-polyfill.js either in your document head, with the defer
attribute or at the end of your document body
.
Once the polyfill’s CSS and JavaScript is in place, register each dialog
element using the dialogPolyfill.registerDialog()
method. For example:
const dialogs = document.querySelectorAll('dialog');
Array.from(dialogs).forEach((d) => {
dialogPolyfill.registerDialog(d);
})
Polyfilled dialog
elements work much like native ones, although the markup differs slightly. Try the demo below. Note that dialog
support is incomplete and disabled by default in Firefox ≤ 59. The backdrop you'll see is markup generated by the polyfill.
I've also tweaked the user-agent styling for the dialog
element in this demo. The default style is … not so aesthetically pleasing.
Determining whether a dialog is open
To test whether a dialog is open or closed, check the value of its open
attribute.
const dialog = document.getElementById('newsletter_dialog');
console.log(dialog.open);
Here dialog.open
returns a boolean value — true
if it's open and false
if it is not.
Multiple dialogs can be open at the same time. In Chrome and Opera, However, dialogs opened with showModal()
prevent interaction with elements below it in the stacking order. Use DOM scripting to guarantee that when you open one, you close the others on the page. the others , you'll need to add some DOM scripting.
Dialogs and forms
Dialogs can contain just about any element, including forms. When used with <form method="dialog">
2, we can create dialogs that are far more than window.confirm()
and window.prompt()
.
Setting a form's method to dialog
tells the browser that the form should not make a server request. Instead, submitting the form will:
- close the dialog;
- dispatch a
close
event on the dialog element; and - update the
returnValue
property of the dialog element.
We can then do something based on the value returned.
const dialog = document.querySelector('dialog');
dialog.addEventListener('close', (event) => {
// Passes the value of the clicked button to this function
doSomethingWithTheAnswer(event.target.returnValue);
});
Here's what this might look like in practice (view source). Note: this demo only works in Google Chrome or with the dialog polyfill. It does not work with Firefox’ implementation (as of version 59) because it is incomplete.
With the dialog
element, you can create styleable modals and confirmation messages that take advantage of browser-native accessibility features. Use it to replace existing modal components based on div
elments. You can also use styled dialog
elements in place of the alert()
, confirmation()
and prompt()
methods of the window
object.
-
Technically, the WHATWG's version of the specification is a
Living Standard
— unversioned, and updated more frequently as new element and APIs are proposed or removed. Read HTML5 is done, but two groups still wrestle over Web's future for a little more context. Although the W3C is widely viewed as the official specification, most browser vendors rely on the WHATWG specification. ↩ -
Firefox supportsRead more about::backdrop
, but doesn't yet support::backdrop
when used with thedialog
element.<form method="dialog">
in the HTML5 specification. ↩