Skip to Content
Course content

129: ARIA Roles and Live Regions in Dynamic UIs

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Most of the time, when we update the DOM with JavaScript, we're thinking about the visual transition. We see the list filter, the spinner disappear, or the error message pop up. But for someone using a screen reader, the page is essentially static unless the focus moves. If you update a piece of text in a div, the screen reader doesn't magically announce it—the user has no idea anything happened.

To fix this, we use ARIA (Accessible Rich Internet Applications) roles and live regions. Let's build a real-time search filter for a user directory to see this in action.

Setting up the search list

I'll start with a basic input and a list of names. Nothing fancy here; just standard HTML. I want a place where I can explicitly tell the user how many results were found, because that's the piece of information that changes dynamically.

<div class="search-container">
  <input type="text" id="user-search" placeholder="Search users...">
  <p id="results-count">Showing all users</p>
  <ul id="user-list">
    <li>Alice</li>
    <li>Bob</li>
    <li>Charlie</li>
    <li>Diana</li>
  </ul>
</div>

Making the filter actually work

Now for the JavaScript. I'm going to listen for the input event and toggle the visibility of the list items. I'll also update the text of that results count paragraph so the visual user knows what's happening.

const searchInput = document.getElementById('user-search');
const resultsCount = document.getElementById('results-count');
const users = document.querySelectorAll('#user-list li');

searchInput.addEventListener('input', (e) => {
  const term = e.target.value.toLowerCase();
  let count = 0;

  users.forEach(user => {
    const match = user.textContent.toLowerCase().includes(term);
    user.style.display = match ? '' : 'none';
    if (match) count++;
  });

  resultsCount.textContent = `Found ${count} user${count === 1 ? '' : 's'}`;
});

The invisible wall: Why users can't "hear" the results

If you run this now and use a screen reader (like VoiceOver or NVDA), you'll notice a problem: as you type, the list shrinks and the "Found X users" text updates, but the screen reader stays silent. It's still focused on the input box. The user has to manually tab away from the search box to find out if their search actually returned anything.

This is where aria-live comes in. By adding aria-live="polite" to our results count, we tell the browser: "When the text inside this element changes, please announce it to the user, but don't interrupt them if they're in the middle of doing something else."

I'm also going to add role="status". While aria-live="polite" does the heavy lifting, role="status" is a specialized ARIA role that implies a polite live region, making our intent clearer to different assistive technologies.

<p id="results-count" role="status" aria-live="polite">Showing all users</p>

Tuning the noise with polite live regions

Here is where I usually make a mistake when I'm in a rush: I'm tempted to use aria-live="assertive". I think, "I want the user to know immediately that the results changed!"

Don't do that. I tried it on a similar project last year, and it was a nightmare. assertive interrupts the screen reader mid-sentence. Since this is a search input, the screen reader is already announcing the letters as the user types. If I use assertive, the "Found 3 users" announcement will cut off the announcement of the character they just typed. It creates a stuttering, chaotic experience.

Stick with polite for search results. It waits for a natural pause in the speech flow before announcing the update. It's a much smoother experience for the user. If you were building a critical system error or a session timeout warning, assertive would be the right call—but for a search filter, it's overkill.




📋 Practical Task

Build a Live Validation Message for a Password Field

Create a password input field and a sibling div or span that acts as a validation message. Write a JavaScript function that checks the password length as the user types. If the password is shorter than 8 characters, display "Password too short" in the message element; otherwise, display "Password length is valid."

Your goal is to ensure that a screen reader user is notified of the validation status automatically without having to move their focus away from the input field. Apply the correct ARIA role and live region attributes to the message element to ensure the notification is helpful but not disruptive.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.