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 the autofocus attribute, while show() may not.
  • Chrome and Opera render showModal() Dialogs opened using showModal() render with a backdrop. Those opened using show() do not.
  • Dialogs opened with showModal() can be closed with the Esc key. Those opened with show() 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.


  1. 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. 

  2. Firefox supports::backdrop, but doesn't yet support ::backdrop when used with the dialog element. Read more about <form method="dialog"> in the HTML5 specification

Subscribe to the Webinista (Not) Weekly

A mix of tech, business, culture, and a smidge of humble bragging. I send it sporadically, but no more than twice per month.

View old newsletters