A dialog is a component of web interfaces providing important information and requiring user interaction in response. The user’s attention should be focused exclusively on the active dialog element, both visually and interactively. Information and user actions presented by the dialog should be phrased simply and unambiguously. So, a dialog is interruptive by nature and should be used sparingly.
Usage Imagine a user browsing a web application from a mobile phone. The application needs the user’s decision about its settings immediately in order to keep functioning properly – like enabling location services in order to give directions on a map. This could be a use case for a dialog:
Structure A modal dialog consists of a container, title, description, buttons and a backdrop. If the user’s flow browsing the application must be interrupted anyway, the least we can do is to present the user a concise and well structured, clear dialog to attract their focus and quickly make an action in order to continue browsing.
Basic structure of a modal dialog It’s essential to phrase a clear and unambiguous message in the title, so the reader can understand it at a glance. Here is one example:
Of course, further information can be put in the body of the dialog itself, but the gist should be comprehensible by reading the title and button texts only.
Behavior A dialog always needs to suit a notable purpose: Getting the user to make a choice in order to finish a task or to keep the application functioning properly (like enabling location services for navigation).
Should the dialog close by clicking the backdrop? Well, I only asked myself this question after trying to implement that behavior with the native dialog element. As it turns out, it’s far easier with ordinary divs to achieve.
Without the native dialog element, your markup would look something like this:
```
```
And the corresponding CSS
.backdrop {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
Here we have an ordinary div stretching out over the full viewport. We can easily grab that div.backdrop with JavaScript and implement our “close-modal-on-click-behavior”.
``` const backdrop = document.querySelector(".backdrop"); const dialog = document.getElementById("dialog");
backdrop.addEventListener("click", function() { dialog.style.display = none; }); ```
So, why can’t we do exactly this with the native dialog element?
The native dialog element comes with a pseudo-element called ::backdrop when invoked with dialog.showModal(). As the name suggests, it is not part of the DOM, and so we cannot access it using JavaScript…
How can we add an event listener on an element, which is essentially not part of the DOM? Well, there are workarounds, like detecting a click outside of the active dialog, but that’s a completely different story.
And once I’ve come to understand, that it is not that easy, I’ve revisitied the initially posed question: Is it worthwhile to close the dialog on click outside?
No, it is not. Keep in mind, that we wanted the user to make a decision. We interrupted the user’s flow of browsing the application. We phrased the message clearly and directly, so that it’ll be comprehensible at a glance. And then we allow the user to dismiss everything we have carefully put together with a single click?! I don’t think so.
Implementation When we implement a dialog, the following requirements must be observed carefully:
Requirements marked with (*) are handled by the native dialog element out of the box, when opened as a modal.
So in order to get all the benefits listed above, we’re going to invoke the dialog using the method showModal provided to us by the native dialog JavaScript API.
// Open dialog as a modal
const dialog = querySelector("dialog");
dialog.showModal();
Example HTML structure
```
<dialog aria-labelledby="dialog_title" aria-describedby="dialog_description"
![]()
Use location services?
In order to give directional instructions, we kindly ask you to turn on the location services.
```
Because we’re using the native dialog element here, we do not need to use role="dialog", modal="true" or similar for an accessible implementation.
Based on this simple HTML structure, which is taken from the example CodePen shown at the end of this article, we can now go ahead and implement the requirements listed above. Once the reader clicks the “Open Dialog” button, the first interactive element inside the dialog will receive focus by default.
Return focus to last active element after closing the dialog The HTML of a modal dialog can be placed nearly anywhere in the page’s markup. So, when the reader opens the modal, the user agent jumps to the dialog’s markup, like using a portal. Once the reader closes the dialog again, the focus needs to be returned back to the element that the reader was interacting with before opening the dialog. The portal to and from the dialog should go two-way, otherwise the reader will get lost.
``` const dialog = document.querySelector("dialog"); const openDialogBtn = document.getElementById("open_dialog"); const closeDialogBtn = document.getElementById("close_dialog");
const openDialog = () => { dialog.showModal(); };
const closeDialog = () => { dialog.close();
// Returns focus back to the button // that opened the dialog openDialogBtn.focus(); };
openDialogBtn.addEventListener("click", openDialog); closeDialogBtn.addEventListener("click", closeDialog);
// If the buttons of the dialog are contained inside a