Dialogs, Alerts or Alertdialogs?

Dialogs, Alerts or Alertdialogs?

That is the question... Let's quickly and easily claryfy the difference and why they're important.

We have seen these role types in other articles, but, in detail, what's the difference, and why should you bother? They all serve the purpose of presenting content over the page, but the urgency and the kind of interaction expected from the user will help you choose.

Alert

You use an alert for important information, often time-sensitive, that requires immediate attention. Alerts should only contain text content, so no such things as links or buttons: for this you don't need to worry about redirecting focus, as screen readers will automatically announce them.

Setting role="alert" is equivalent to setting aria-live="assertive" and aria-atomic="true"

Being "assertive", the alert role should be used sparingly and only when the user's attention is immediately required.

<div
  role="alert"
  aria-labelledby="dialog__title"
  aria-describedby="dialog__content">
    <h2 id="dialog__title">Yo! I'm the title</h2>
    <p id="dialog__content">And I'm the content</p>
</div>

Dialog

The <dialog> HTML element (or an element with role="dialog") represents a dialog box or other sub-window-like, modal, interactive component and it provides some features that must be replicated if using other elements for a similar purpose.

By using a <dialog> (that is an HTMLDialogElement) JS gives you the following methods out-of-the-box:

  • yourDialog.showModal() - displays the modal and allows "Escape" to close it

  • yourDialog.show() - as above, but without "Escape" closing mechanic

  • yourDialog.close() - closes the modal

  • yourDialog.returnValue() - takes the value of the submit button clicked to close the modal

Also, CSS gives you an extra pseudo-class for free when using the .showModal() method!

  • ::backdrop - lets you specify a background-color that will stay below your dialog covering the entire page

More: submitting a <form> contained in the dialog has a special behaviour: clicking on a submit button will not submit it, but will "save" the values, that you can access using the yourDialog.returnValue.

By executing these opening methods, JS will add the open attribute to your dialog, otherwise, it will simply not be visible.

Labeling

Labeling here is quite straightforward. Dialogs need to be labeled and you can use the title itself (if present) with aria-labelledby or go with aria-label, to keep that integrated into the element. You should also have an aria-describedby in your dialog, linked to the main content or to a hidden element containing additional info on how to interact with the modal and its content.

Focus management

Everything's great up to this point. What's left is focus management, and unfortunately, it's not a secondary matter, nor an easy task, but we'll make it easy. "Divide and conquer" is the key:

  • Focus grabbing: HTMLDialogElement.showModal() sets automatically focus on the first focusable element, just like it should. When dealing with dynamic content you could also consider focusing on the <dialog> itself.

  • Focus looping: focus must not go outside the modal, so you have to manually manage this behaviour via JS (no native support available, sorry!); but luckily, I've done an article right about this topic (read Focus Trapping now!).

  • Focus returning: when the user has finished dealing with the modal, focus has to return to the element that initially triggered the modal itself or, optionally, to the next logic step.

<dialog
  aria-labelledby="dialog__title"
  aria-describedby="dialog__content">
    <h2 id="dialog__title">Yo! I'm the title</h2>
    <p id="dialog__content">And I'm the content</p>
    <button type="button">OK</button>
</dialog>

Alertdialog

The alertdialog role, as you can imagine, is a sort of hybrid between the two previous roles. They interrupt the user's flow for important matters like alerts, but require explicit interaction like dialogs: for this reason, they must have at least one focusable control.

With this role, all the bells and whistles above about focus, backdrops and navigation deactivation must be implemented manually.

<div
  role="alertdialog"
  aria-labelledby="dialog__title"
  aria-describedby="dialog__content">
    <h2 id="dialog__title">Yo! I'm the title</h2>
    <p id="dialog__content">And I'm the content</p>
    <button type="button">OK</button>
</div>

Note about aria-live

Alerts, dialogs and alertdialogs are aria-live elements: they're meant for dynamically displayed content, and they'll be correctly announced when their content CHANGE. This means that the container (with aria-live) must be present in the DOM before its content changes (or is populated). Adding to the DOM an already populated element will not grant to be read, 'cause "de facto" its content doesn't change.

You can read a more in-depth explanation in this other article.