HTML dialog Element
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>
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>
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.