Accessible Alerts made easy by the Popover API
Alerts are a common pattern on the web. They show an important message in a way that attracts the user's attention without interrupting the current workflow. For example: “Item was added to your cart”, or “Login has failed: Check username/password”.
Creating accessible and nicely animated alerts will become a lot easier in the near future, thanks to the new Popover API and new capabilities of CSS transitions. I've prepared a demo that you can try out.
Photo: © Thirdman / pexels.com
If you're not familiar with the Popover API, go read my article “Make your content pop with the Popover API and CSS Anchor Positioning” first. I won't repeat the basics of the API and instead focus on the relevant parts of this specific use case.
Accessible Alerts Demo
Here's my demo of accessible alerts using the Popover API. You can adapt the message as well as the duration and position of the alert. Give it a try:
The alert appears above all other elements of the page and is automatically announced by screen readers. I've tested this behavior with JAWS, NVDA, TalkBack and VoiceOver. The alert doesn't interrupt the user's current task and disappears after some time.
Implementation Details
Now let's examine the different building blocks that I used to create the accessible, animated alerts.
Generating dynamic HTML
I've implemented an Angular service that dynamically generates
the popover element using JavaScript methods like createElement()
and appendChild()
. Check out the demo code
for more details. You don't need to be familiar with the Angular framework to understand the important parts.
The following HTML code is appended to a container at the end of the body element:
<div popover="manual" role="alert" class="alert top-right">
This is a very important message
</div>
The popover
attribute turns the div
element into a popover that
is initially hidden by the browser. We show the popover alert by calling the element's
showPopover() method.
Setting popover="manual"
on the element defines a manual popover state. This prevents
light-dismiss, meaning, interacting with other elements on the page won't close the popover. We close the popover
programmatically using the hidePopover() method.
Semantic Markup
Set role="alert"
on the popover element to define it as an alert. The document
Accessible Rich Internet Applications (WAI-ARIA) 1.2
describes the alert role as follows:
A type of live region with important, and usually time-sensitive, information. [...] Alerts are assertive live regions, which means they cause immediate notification for assistive technology users.
In general, we use ARIA live regions
to communicate dynamic content changes. Setting role="alert"
is actually equivalent to
setting aria-live="assertive"
and aria-atomic="true"
. This means, as
soon as our popover alert is displayed, screen readers immediately announce the alert's message.
Animation
Now let's put the icing on the cake. Let's add some animation to the popover element. There's only one problem: Popovers
are initially hidden via display: none
. What a nightmare! This creates two obstacles:
- An element with the
display
property value ofnone
is not rendered. Therefore, it has no computed values for the different CSS properties like, e.g.,opacity
. If there is no computed value, you have no starting point for the transition. - The same problem exists the other way around: When the
display
property is set tonone
, it immediately takes the element out of the flow of the rendered HTML document without triggering the transition effect.
Lucky for us, the CSS Transitions Level 2 specification adds new capabilities
to CSS transitions. It defines the new @starting-style
rule:
The @starting-style rule is a grouping rule. The style rules inside it are used to establish styles to transition from, if the previous style change event did not establish a before-change style for the element whose styles are being computed.
This allows us to define a starting state for our transition when the display type changes from none
to another type.
The second piece of the puzzle is the new transition-behavior
property and
its allow-discrete
value:
The transition-behavior property specifies whether transitions will be started or not for discrete properties.
Discrete properties have values that can't be interpolated. This is the case, e.g., for the display
and overlay properties. To allow transitions for them, we need to
set the allow-discrete
value. You can also include
the transition-behavior
value as part of a shorthand transition
declaration.
How does it all fit together? My demo includes the "top-right" position, where the alert fades in and slides in from the right. Here's the CSS code for the transition:
.alert[popover].top-right {
/* Final state of the exit animation */
opacity: 0;
transform: translateX(100%);
transition: opacity 0.5s,
transform 0.5s,
overlay 0.5s allow-discrete,
display 0.5s allow-discrete;
}
.alert[popover].top-right:popover-open {
/* Final state of the show animation */
opacity: 1;
transform: translateX(0);
}
/* Needs to be after the previous [popover]:popover-open rule to take effect, as the specificity is the same */
@starting-style {
.alert[popover].top-right:popover-open {
opacity: 0;
transform: translateX(100%);
}
}
In the example above, the opacity
and transform
properties
are transitioned for a duration of half a second. We want the browser to show the transitioned content and keep the
popover in the top layer for the entire animation duration.
To achieve this, we also include overlay 0.5s allow-discrete
and display 0.5s allow-discrete
in the transition.
Warning: These features are experimental and might change in the future!
Browser Support
The popover
attribute is already supported in all major browsers.
At the time of writing this article, Firefox had only enabled the feature in its experimental Nightly builds. But I expect
Firefox to release the feature soon.
The new transition capabilities are only supported by Chrome and Edge at the moment. I'm hopeful that they'll be part of Interop 2024 and reach cross-browser compatibility until the end of the year.
Useful Resources
Posted on