Introduction

Modals suck.

Any front-end developer has likely experienced the pain of covering an exhaustive list of accessibility and UI edge cases while implementing modals. Well guess what? Not any longer.

Now there’s a native HTML element, <dialog> which covers both modals and dialogs. Support for tab control, content hiding, focus management — it’s all managed out of the box, no code required. Modals made so simple it’s crazy.

Recently, support for this feature landed in all major browsers, making it a particularly exciting time to incorporate dialog boxes into web projects. This blog post walks through the process of creating and interacting with the dialog element.

We’ll start by exploring the basics of the dialog element, discussing its key attributes and how to structure it for optimal usage. We’ll then delve into the details of the open and close methods, which control the visibility of the dialog box. In the process, we’ll cover both ‘dialog’ and ‘modal’ roles of the dialog element, exploring the differences and best practices for each.

We’ll also address a common aspect of modal dialogs: the ability to close the modal by clicking outside of it. This feature is not inherent to the HTML dialog element, but we’ll implement it using JavaScript.

While up to date as of May 2023, check the most recent documentation when working with HTML elements. Find the official documentation for the HTML dialog element here, and if encountering any compatibility issues, the dialog-polyfill package can be a useful resource, which is here.

The Simple Modal Dialog Element

Meet the <dialog> element, the new HTML-native solution to the modal dialogue problem. This HTML element comes equipped with features that were previously only achievable with complex JavaScript, CSS, and ARIA roles.

The <dialog> element has two primary roles: ‘dialog’ and ‘modal’. The ‘dialog’ role is the default state, where the <dialog> element is treated as part of the regular document flow, and interaction with the rest of the page is still possible. The ‘modal’ role, on the other hand, makes the <dialog> element behave like a traditional modal, where interaction with the rest of the page is blocked until the modal is closed.

A simple example of the <dialog> element in action might look like this:

<dialog open>
<p>This is a simple dialog box. It’s open because it has the ‘open’ attribute.</p>
</dialog>

The dialog is open because it has the ‘open’ attribute. Note also the content, nested inside.

This boolean attribute controls the visibility of the dialog box – when present, the dialog is shown; when absent, it’s hidden. But changing this attribute in the HTML file every time we want to show or hide the dialog isn’t practical. That’s where the open and close methods come in.

The open and close methods allow us to dynamically control the visibility of the dialog box using JavaScript. Here’s how:

<dialog id=”myDialog”>
<p>This is a simple dialog box. It’s not visible by default because it doesn’t have the ‘open’ attribute.</p>
</dialog>

<script>
let myDialog = document.getElementById(‘myDialog’);

// To open the dialog
myDialog.show();

// To close the dialog
myDialog.close();
</script>

This is invisible by default because it doesn’t have the ‘open’ attribute. It hides without any css work too, another major advantage over implementing standard modals.

In this example, we first get a reference to the dialog element using its id. Then, we can call the show method to add the ‘open’ attribute and make the dialog visible, and the close method to remove the ‘open’ attribute and hide the dialog.

It’s also important to note that the show method opens the dialog as a ‘dialog’, while the showModal method opens it as a ‘modal’. Here’s an example:

 

<dialog id=”myDialog”>
<p>This is a simple dialog box. It’s not visible by default because it doesn’t have the ‘open’ attribute.</p>
</dialog>

<script>
let myDialog = document.getElementById(‘myDialog’);

// To open the dialog as a dialog
myDialog.show();

// To open the dialog as a modal
myDialog.showModal();
</script>

In this code snippet, calling myDialog.showModal() opens the dialog in a way that blocks interaction with the rest of the page, similar to traditional modals. Yeah, creating an entire modal with one method on the same element.

Those are the basics! Let’s dive into the details.

 

Interacting with the Modal Dialogue

Tabbing

Done.

Yes, that’s right, focus is automatically contained within the modal, it is impossible to move focus outside the modal, as its context is actually not in the same body — it uses a new section called the top layer, which means not only does it avoid the need to manage focus, z-index battles are a nonexistent issue. This element floats above any content, no matter the z-index used.

Additionally, focus returns automatically to the triggering element on close.

Escape Key

The non-modal dialog does not close by default when pressing the escape key; the modal does.

Click Off Functionality

One common feature of modals is the ability to close them by clicking outside of the modal box. This feature is not inherent to the dialog element but can be added using JavaScript.

document.addEventListener( ‘click’, function(event) {
let dialog = document.querySelector(‘dialog’);
if (!event.target.closest(‘dialog’)) {
dialog.close();
}
});

This code adds a click event listener to the document. If a click event occurs outside of the dialog box, the dialog’s close method is called, closing the dialog box. A good practice here is to check if what was clicked is the pseudo element the modal adds to the page. As it is native, this element is guaranteed each time.

These methods offer a more flexible way to control the visibility of dialog boxes and modals, making it easier to create interactive and user-friendly interfaces.

Styling the Modal Dialog Element

So is this magical new element deeply embedded in the engine and impossible to style? Not at all!

The <dialog> element, while being impressively feature-rich, is also quite accommodating when it comes to styling. It’s not constricting like a typical <select> dropdown, which by default defies conventional CSS rules and requires exhaustive hacks to style in a decent manner.

The <dialog> is just another HTML element. Style it with CSS just as any other HTML element.

dialog {
width: 80%;
border: none;
border-radius: 8px;
padding: 20px;
background-color: #f1f1f1;
}

This CSS code snippet directly affects the dialog box, and the element doesn’t fight against the border radius or background color.

Conclusion

And there we have it – the exciting new HTML <dialog> element. It’s easy to implement, wonderfully feature-rich, and a significant leap forward in making modals less of a pain for developers. With browser support expanded, this is the future of modals and dialog boxes.

Disclaimer

I wrote more than half of this blog with AI! I think AI will change the world, and I’ve written blogs comparing them, showing how to use them, and more. Check them out if interested.