HTML dialog Element

#

I'm a dialog.

I'm a dialog.

This biggest difference to note between these two elements is that when the modal is open you cannot do anything on the page except for scroll. All other interaction is blocked until you explicitly close the modal. On the other hand, when the dialog is open you can still interact with the page just like normal.

dialog Element Basics

Now that we understand what modals and dialogs are we can look at the new HTML dialog element. The actual dialog element itself is very easy since it is just a single element that only has one custom attribute that you can add to it. It also acts similarly to a fancy div since you can put anything you want in the dialog element and it is also very easy to style exactly how you want.

<dialog>
  <!-- Dialog Content -->
</dialog>

By default a dialog element will be hidden unless you add the open attribute to your dialog

<dialog open>
  <span>You can see me</span>
</dialog>

It is not advised to use the open attribute directly, though, as that only allows you to open a non-modal dialog. Instead, you should use the show() and showModal() JavaScript methods.

const dialog = document.querySelector("dialog")
dialog.show() // Opens a non-modal dialog
dialog.showModal() // Opens a modal

By using the show() and showModal() methods you can choose exactly how you want your dialog element to work since sometimes you want a true modal while other times you want more of a popup style dialog. To close a dialog element you just need to use the close() method.

Alternatively, if your dialog element is a modal you can use the Esc key to close it.

const dialog = document.querySelector("dialog")
dialog.close() // Closes the dialog

This already makes working with modals/popups so much easier, but the real benefit of the dialog element is that it handles accessibility for you by default. All the proper aria-attributes and focus states are taken care of for you so you don't have to worry about any of that. I love this since it makes writing accessible apps so much easier.

dialog Element Styling

Another thing I love about the dialog element is how easy it is to style. There are a few default styles applied to the dialog element (depending on if it is a modal or not) that give you the basics, but since the dialog element is essentially just a fancy div you can style it however you want. The below button opens a custom styled dialog with the following styles applied.

dialog {
  z-index: 10;
  margin-top: 10px;
  background: green;
  border: none;
  border-radius: 1rem;
}

On top of being able to style the dialog element itself, you can also style the backdrop that appears behind the dialog without any custom HTML or JavaScript. As long as you have a modal dialog you can style the backdrop by using the ::backdrop pseudo-element. The below modal has the following styles applied to the backdrop to give it a purple color.

dialog::backdrop {
  background-color: hsl(250, 100%, 50%, 0.25);
}

The combination of the ::backdrop pseudo element and the fact that styling the dialog element is as easy as styling a div makes it so easy to create custom modals that fit your site's design.

Advanced dialog Features

Overall the dialog element is pretty simple to use, but there are a few advanced things you can do with the dialog element.

Forms

If you have a form in your dialog you can set the method attribute of your form to dialog. This will cause the form to close the dialog when it is submitted and most importantly it will NOT submit your form. Instead the form data will be saved so if you reopen the same dialog your form will have all the same data in it. Here is an example below.

<dialog>
  <form method="dialog">
    <input type="text" />
    <button type="submit">Submit</button>
  </form>
</dialog>

Also, you may have noticed that the input element was automatically focused when the modal was opened. This is yet another accessibility feature you get by default from the dialog element.

This can be taken a step further since on any submit button in your form you can add the formmethod="dialog" attribute to make that button act as if the form method was set to dialog. This is useful if you want to have a cancel button in your form that closes the dialog without submitting the form while the normal submit button would submit the form. Here is an example below.

<dialog>
  <form>
    <input type="text" />
    <button formmethod="dialog" type="submit">Cancel</button>
    <button type="submit">Submit</button>
  </form>
</dialog>

Close On Outside Click

One thing that we are used to with most modals is the ability to close a modal when clicking outside of it. This is not something that is built into the dialog element, but it is something that is easy to add. All you need to do is add a click event listener to the dialog element. This will trigger if you click anywhere inside the modal or anywhere inside the ::backdrop since the ::backdrop is a child of the dialog element. Then all we need to do is see if the click was inside the dialog element or not. If it was not then we can close the dialog. Here is an example below.

Although the alert, confirm and prompt JavaScript methods are convenient, they aren’t recommended due to their script-blocking behavior. That’s why we worked with other browser vendors to drive improvements to the <dialog> specification over the last few years. The most important conversations involved accessibility.

You can find more complex use-cases, like payment dialogs, on the web. They are currently addressed by custom solutions from frameworks like Bootstrap. Unfortunately, they aren’t convenient to use and aren’t always accessible. We believe the web deserves a simple and bug-free solution for these use-cases. Safari Technology Preview 134 and Safari 15.4 beta introduces the <dialog> element for this reason!

How Do I Use <dialog>?

Let’s create a simple confirmation dialog:

<dialog id="confirmation-dialog">
    <h1>Do you want to delete everything?</h1>
    <p>You will lose all your data.</p>
    <button id="cancel-delete">Cancel</button>
    <button id="confirm-delete">Delete!</button>
</dialog>

Dialogs are hidden by default. We can use the showModal() method to show the dialog. When it’s shown, the dialog can be closed with the close() method.

Here is an example:

<button id="delete">Delete everything</button>
<p id="result"></p>
<script>
let dialog = document.getElementById("confirmation-dialog");
let result = document.getElementById("result");

// Show the dialog when clicking "Delete everything"
document.getElementById("delete").addEventListener("click", function() {
    dialog.showModal();
});

document.getElementById("cancel-delete").addEventListener("click", function() {
    dialog.close();
    result.textContent = "Canceled!";
});
document.getElementById("confirm-delete").addEventListener("click", function() {
    dialog.close();
    result.textContent = "Deleted!";
});
</script>

Do you want to delete everything?

You will lose all your data.

Note that the dialog will get an open attribute once opened, which may be useful for styling purposes. However, it’s not recommended to toggle this attribute manually to show or hide the dialog, since the browser may lose track of the dialog state, and will not perform proper focus adjustments for accessibility.

Styling

The semi-transparent box behind the dialog that you may have noticed from previous examples is the ::backdrop pseudo-element. By default, it is styled so it covers the whole viewport. Like the dialog itself, you can style the backdrop using CSS. Animations can also be used if you would like to add a fade-in effect for instance.

Note that the backdrop is only shown for modal dialogs.

Here is an example:

<dialog>
    <h1>This is a pretty dialog</h1>
    <p>The backdrop animates!</p>
</dialog>

<button onclick="document.querySelector('dialog').showModal()">Show the dialog</button>

<style>
dialog {
    box-shadow: 0 2px 5px rgba(0,0,0,0.3);
    border: none;
    border-radius: 10px;
}

dialog::backdrop {
    background: linear-gradient(rgba(0,0,0,0.1), rgba(0,0,0,0.4));
    animation: fade-in 1s;
}

@keyframes fade-in {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}
</style>

This is a pretty dialog

The backdrop animates!

Pretty dialog example styled and animated

Accessibility

For accessibility tools, the <dialog> element is equivalent to role="dialog". In addition to that, a modal dialog will behave similarly to an element with aria-modal="true".

Users can dismiss modal dialogs using the “Escape” key on desktop browsers. That will trigger a cancel event which you can intercept. If multiple modal dialogs are opened, the one shown last will be dismissed.

It is also possible to specify an element to initially focus on when opening dialogs by adding the autofocus attribute to the relevant element.