Enhance Dialogs with the closedby Attribute

Posted on

The native <dialog> HTML element is a thing of beauty. It enables you to easily create accessible, modal dialogs that work well for all users. And it has been supported by all modern browsers since 2022.

But it gets even better: The new closedby attribute allows you to define which user actions will close the dialog. You can add light dismiss behavior, or go the other way: e.g., prevent the ESC key from closing the dialog.

Two white speech bubbles on a pink background.

We’ll take a look at the technical specification and some use cases for the new attribute.

How it works

The HTML specification defines closedby as an enumerated attribute with the following keywords:

If you don’t set the closedby attribute on a modal dialog, then it behaves as if the value was closerequest . This means, pressing the ESC key on desktop platforms, or a “back” or “dismiss” gesture on mobile platforms, will close the dialog.

Use Cases

Light Dismiss for Informational Dialogs

Some dialogs only present information. The user isn’t expected to make a decision or fill in a form. In my opinion, this is a perfect use case for adding light dismiss behavior: The dialog should close when the user clicks or taps outside it.

Before we had the closedby attribute, you needed additional JavaScript code to implement light dismiss. See my article “Why you should use the Native Dialog Element” for an example. Lucky for us, now we only need the following HTML code:

<dialog closedby="any">
    <!-- content -->
</dialog>

Awesome! 🥳

Prevent Accidental Closing

Dialogs are a great way to encapsulate workflows like, e.g., the data entry via a form. You can also handle the onboarding process for your web application with a dialog.

In all these cases, you’ll want to prevent the user from accidentally closing the dialog, e.g., via the ESC key. They would lose the data they had already filled in the form, or not be able to access the onboarding dialog again.

Therefore, you should set closedby=“none” on the dialog. Now the user can only close the dialog via a developer-specified mechanism, like a close button. Here’s an example:

<dialog id="mydialog" closedby="none">
    <!-- content -->
    <button commandfor="mydialog" command="close">
        Continue
    </button>
</dialog>

Maybe you’re wondering about the command and commandfor attributes on the close button. They’re part of a new web feature called Invoker Commands API. You don’t have to use them in your dialogs. But I like their simplicity and elegance, so I wanted to include them in my code example. 😉

Browser Support

The closedby attribute is already supported by Firefox, Chrome and Edge. Thanks to Interop 2026, Safari/WebKit should catch up until the end of the year.

Useful Resources

Posted on