The dialog element

Simplify pop-ups and modals using the HTML dialog element.

Let's talk about pop-ups. And modals, overlays, or anything else you like to call them (remember Lightbox?). Despite user experience concerns, these elements remain popular on the web. But technical implementations can be wildly inconsistent. Looking to stop reinventing the wheel? This post will help guide you in your quest to show content on top of other content.

Problem

Implementing solutions for pop-ups can be difficult. What seems trivial on the surface can become more complicated in a hurry. You may need to account for modal and popover designs. And animations. How about custom behavior on form submissions? What happens if there is more than one modal trying to display at the same time?

To help with that, you may reach for a plugin solution. But there are so many choices, and a lot of topics to consider:

  • API
  • Accessibility
  • Dependencies. You might not want jQuery, React, or similar.
  • Support. Who is maintaining it? How soon are issues addressed? 
  • Extensibility. How easy is it for me to customize and add new features?

Of course you may choose to build your own instead. But how flexible is it? Can you reuse as-is in other places? What about other projects?

Solution

Enter the HTML dialog element! Published in HTML 5.2 (2018), <dialog> is a native browser element for creating pop-ups and modals.

<dialog open>
  <h1>Hello</h1>
</dialog>

A dialog element provides:

  • An element that is easy to show and hide, including an open boolean attribute on the element itself.
  • Two versions: a standard popover or modal version.
  • A ::backdrop pseudo-element for modal types.
  • Built-in focus: see dialog focusing steps.
  • ARIA role support (dialog is the implied default). Also accepts the alertdialog role.
  • A pending stack for multiple dialogs.
  • A DOM interface with the open boolean and methods show , showModal , and close.

And those are just some highlights! Showing content on top of other content has never been easier.

Standard Use

<dialog id="dialog">
  <h1>Hello</h1>
</dialog>

<script>
  var dialog = document.getElementById('dialog');
  dialog.show();
</script>

Modal Use

The modal version is activated by method, i.e. dialog.showModal(). This differs from standard use in a couple of ways:

  • Guaranteed to be on top of any other elements regardless of their z-index.
  • dialog::backdrop provided for styling.
  • Close with Esc key.
<dialog id="dialog">
  <h1>Hello</h1>
</dialog>

<script>
  var dialog = document.getElementById('dialog');
  dialog.showModal(); // "showModal" instead of "show"
</script>

::backdrop

Target dialog::backdrop to style the background of a modal dialog. Really handy for a semi-transparent background overlay.

dialog::backdrop {
  background-color: rgba(0, 0, 0, 0.8);
}

Dialog Forms

A new form attribute, method="dialog", can be used within dialog elements. Specifying the attribute provides the contents of the submit button's value attribute to the dialog element itself.

<dialog id="dialog">
  <form method="dialog">
    <p>Would you like to continue?</p>
    <button type="submit" value="no">No</button>
    <button type="submit" value="yes">Yes</button>
  </form>
</dialog>

<script>
  var dialog = document.getElementById('dialog');
  dialog.showModal();
  dialog.addEventListener('close', function (event) {
    if (dialog.returnValue === 'yes') { /* ... */ }
  });
</script>

Caniuse?

At the time of this writing, browser support for the dialog element is about 70% globally. But there is hope for more. Firefox's implementation is behind a flag. Edge status for the dialog is under consideration, stating "...likely for a future release." You can cast votes supporting development on Edge.

Polyfill

Now you need a polyfill. Audible sigh. That being said, I believe it's worthwhile to continue with dialog, even in this intermediate state. If you're with me, here are two options to consider right now.

Google Chrome Polyfill

Pros: drop-in polyfill from the Google Chrome team. Easy to use. Cons: not super small.

https://github.com/GoogleChrome/dialog-polyfill

a11y-dialog

Pros: very small. Built with accessibility in mind. React and Vue variants available. Cons: requires more markup than a drop-in polyfill.

https://github.com/edenspiekermann/a11y-dialog

React: https://github.com/HugoGiraudel/react-a11y-dialog

Vue: https://github.com/morkro/vue-a11y-dialog

Chris Manning

Chris is a developer who's passionate about web performance. He works in our Durham, NC, office for clients such as ESPN, Dick's Sporting Goods, and the Wildlife Conservation Society.

More articles by Chris