If you have an interface where content is dynamically updated, and when the content is updated it does not receive focus, then you likely are going to need a live region.

Live regions are elements that inform assistive technologies, such as screen readers, that their descendant content may update. And, in such situations those updates need to be relayed to their users.

Live regions may be implemented into a web page via three different methods:

  • Using specific ARIA live region roles, such as alert, log or status. There’s also marquee and timer… but more on those in a second.
  • Using the aria-live attribute to turn “any element” into a live region. There are three states that a live region may be in.
    • assertive: high importance updates which take precedence over other announcements.
    • polite: announcements that will be made at the next opportunity.
    • off: announcements will not be made unless focus is presently on the live region element.
  • Using HTML’s native <output> element. This element has the implicit ARIA role of status.

Why you would use one method over the other will depend on how you want the content exposed to your users.

For instance, you might use one of the ARIA live region roles, or the <output> element, if you intend to both have a section of content that will announce its updates to users, and this section of content would benefit from having its own unique role exposed.

<div role=alert>
  I likely have some sort of design that indicates I'm an alert.
  You know. Like some red, or an exclamation point or something.
  "Pay attention to me" kinda traits.
</div>

You would use an aria-live attribute if you had an element, for instance a <li>, <p>, or a <div>, where the element’s contents can dynamically update, but you either need to maintain the implicit role of the element, or there is no benefit in exposing an explicit role.

<ul aria-live=polite aria-atomic=false>
  <li>My list semantics are important.</li>
  <li>But I want you to know when new list items are added.</li>
</ul>

If you had an element that dynamically updated, but you didn’t want to constantly barrage users with announcements, then you might need timer, marquee, or a generic element with an aria-live=off.

<div role=marquee>
  I'm literally never going to stop talking... so best to ignore me by default.
</div>

Live regions are weird and finicky

While everything I’ve mentioned so far is technically accurate, and the specs for live regions have received very few updates for some time, browsers and assistive technologies are quirky in how they expose live regions. Additionally, explicit instructions on how to implement live regions are rather sparse. There is an Alert example provided by the ARIA Authoring Practices. However, if you’ve spent time testing live regions you might already be aware that there are some unspoken best practices to help make sure live regions consistently (or as consistently as presently possible) work in your web interface.

Non-normative rule for common live region use case

One of the most common use cases for live regions is to announce a notification of some sort. This may range from a notification that visually appears on screen and is available to all users. Or, just as commonly, a live region might be used to indicate that content has updated somehow, but there is no explicit message as the information is visually apparent (e.g., it has started or finished loading). Such a scenario would generally require a visually hidden live region to inform people using screen readers of this state communicated via other visual means.

Many developers, reasonably, have tried to make these notifications clear by injecting a live region containing the necessary text on an as-needed basis. However, if testing beyond macOS VoiceOver, one would find that this is consistently the least supported way to ensure a live region is properly announced by screen readers.

Dynamically injecting a live region node or changing an existing live region from display: none to display: block are effectively the same. In both cases (being absent or set to display: none) the live region does not exist in the a11y tree.

Rather, as the following test cases show, ensuring an empty live region exists in your DOM, and injecting content into it when necessary, proves to be the most robust way to ensure a live region will be announced.

View the live region examples in a new window.

See the Pen live region example by Scott (@scottohara) on CodePen.

I would suggest further testing and re-testing as you implement live regions into your own projects. Results can vary as browsers and AT update. Having done a barrage of testing back in 2019, I’ve found that behaviors have changed enough (slightly for the better), that you should constantly be reviewing your live regions to ensure they are continuing to work as necessary.

As a general rule, if you can create an interface that can limit the number of live regions necessary - none being the ideal - then that’d be for the better.

However, please do keep in mind that something just as bad as live regions being injected into a web page and then making no announcements, is a web page with a bunch of live regions that all start barking at assistive technology users at the same time.

More information on live regions

The ARIA working group is presently planning to take a hard review and look to make serious updates to live regions when work begins on ARIA 1.4. At the time of writing this, ARIA 1.2 has not yet reached W3C rec, but work on ARIA 1.3 has begun.

Additionally, there is this Notification API for Confirmation of Action explainer which would be quite welcome as a way to better standardize live region behaviors.

There many more things to be said about live regions, their use cases and other best practices when using them. I’m not going to write about those though, because Sarah Higley has already delivered an A11yTalks (July 2020) presentation to tell you all about them.