Dialogs, Alerts or Alertdialogs?
That is the question... Let's quickly and easily claryfy the difference and why they're important.
Table of contents
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 ityourDialog.show()
- as above, but without "Escape" closing mechanicyourDialog.close()
- closes the modalyourDialog.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 abackground-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.