Web Dev Simplified Blog

Modals Will Never Be The Same - HTML dialog Element

April 24, 2023

Modals have been a part of web development for decades now, but they have always been a bit of a pain to work with. The main reason modals have been such a pain is because it is difficult to make a truly accessible modal that conforms to all accessibility standards. This is why the new HTML dialog element is so exciting. The dialog element makes it so much easier to create accessible modals, and in this article I will explain everything you need to know about the dialog element to use it in your next project.

If you prefer to learn visually, check out the video version of this article.

What Is A Dialog/Modal?

Before we can jump into the new dialog element, I need to first explain what a dialog is. A dialog/modal is simply a popup that appears on top of the current page. The main difference between a dialog and a modal is that a modal is supposed to take complete priority over the page and prevent the user from interacting with the page until the modal is closed while a dialog, is just a popup that doesn’t take complete priority over the page and should allow the user to interact with the page while the dialog is open.

I am sure you have seen tons of modals/dialogs while browsing the web but below is an example of a simple modal and a dialog so you can see the difference between the two.

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.

dialog.addEventListener("click", e => {
  const dialogDimensions = dialog.getBoundingClientRect()
  if (
    e.clientX < dialogDimensions.left ||
    e.clientX > dialogDimensions.right ||
    e.clientY < dialogDimensions.top ||
    e.clientY > dialogDimensions.bottom
  ) {
    dialog.close()
  }
})

I wish this was something built into the dialog element, but luckily it is easy enough to add yourself.

Conclusion

As you can see the dialog element is relatively easy to use, but incredibly powerful in what it can all do. I love how easy it is to create custom modals and dialogs that fit your site’s design and how easy it is to make them accessible. On top of that, this element has support in every modern browser which means you should be using it anytime you need a dialog or modal.