The HTML dialog element

Reading Time: 3 minutes

Did you know that there’s a dialog element in the proposed HTML 5.1 spec? Did you know that you can use this in Blink-based browsers natively or with a dialog polyfill for other browsers? I didn’t know this until just recently. Here’s what I’ve learned…

The simplest example is just a page that opens and closes a modal dialog.

Native dialog example in action

To make that example happen, we need just a couple items in our page. A dialog element provides the content, and we are embedding a form with the method of “dialog”, which closes the dialog on submit instead of navigating to another page. A button’s click handler is setup to call [showModal]() on the dialog element, allowing the dialog to appear when desired.


<!DOCTYPE html>

<html>

<head>

  <title>Dialogs!</title>

</head>

<body>

  <dialog>

    <form method="dialog">

      This is a dialog!

      <input type="submit" value="Close" />

    </form>

  </dialog>

  <h1>Hi there!</h1>

  <p><button>Open dialog</button></p>

  <script>

    var button = document.querySelector('button');

    button.onclick = function() { document.querySelector('dialog').showModal(); };

  </script>

</body>

</html>

So that’s pretty cool! But that’s not all we can do. We can apply some styling to the backdrop of the dialog via the backdrop pseudo selector. This controls the ‘gray out’ effect when using a modal dialog.


dialog::backdrop {

  background-color: red;

}

And that CSS in action produces a pretty red overlay to all the content.

Dialog with red backdrop

If you want to do this using the polyfill, you’ll need to adjust your selector slightly as the pseudo element doesn’t exist and instead the polyfill creates a new element to take the place of the ::backdrop.


dialog + .backdrop,

dialog::backdrop {

  background-color: red;

}

This is enough to get you started, but there’s a couple other things if you’re interested…

dialog.close() and dialog.returnValue

You can call dialog.close() instead of using a form submit to dismiss the dialog. When you call close you may provide a return value that’s exposed as the returnValue property on the dialog object. This might be handy to ask for and return input in a modal, like [window.prompt].

‘show’ vs. ‘showModal’

The behaviour of ‘show’ and ‘showModal’ differs in display. And ‘show’ does not produce a ::backdrop pseudo element, covering over other content.

dialog.show()

Dialog.show

dialog.showModal()

Dialog.show

dialog.cancel event

If you open a modal dialog, the escape button will close the dialog. You can listen for this event and then use event.preventDefault() to disable this behaviour. dialog.oncancel = function(evt) { evt.preventDefault(); } will do that for you.

dialog.open attribute

You can make the dialog open on page load by adding the open attribute to the dialog element. This opens the dialog as if you used the show method on the element. Calling ‘show’ or ‘showModal’ on the dialog also changes this property.

We can see what’s going on by registering a [MutationObserver], which listens for changes to the DOM.


var observer = new MutationObserver(function(mutations) {

  mutations.forEach(function(mutation) {

    console.log(mutation);

  });

});

var dialog = document.querySelector('dialog');

observer.observe(dialog, { attributes: true });

The MutationObserver shows that the open value changed, but Chrome does not appear to fill in oldValue in this case. You still get notifications that it’s changing — the important part. Hitting open and close a couple times shows the following in Chrome.

MutationObserver results in Chrome

Using dialogs!

There are websites using dialog elements now, and you can too! Now you can replace all those app modal alert dialogs with page or tab modal dialogs!

Thanks to @jasonkarns for bringing this to my attention. Without that, I wouldn’t have spent half a day poking around to bring you all the insight I learned. Follow me @TravisTheTechie on Twitter for more things about the web, LEGOs, and tech.