Curriculum Series

aria-label, aria-labelledby, and aria-live in practice

aria-label, aria-labelledby, and aria-live in practice

aria-label, aria-labelledby, and aria-live in practice

HTMLAccessibility

Why these three come up

If you're interviewing at a company that takes accessibility seriously, expect questions on ARIA. These three attributes are the ones that come up most often — and once you see the specific problem each one is designed to solve, they click quickly.

aria-label

aria-label gives a screen reader a name for an element when there's no visible text to use. The textbook case is an icon-only button — think the little X on a modal dialog.

JAVASCRIPT
1<!-- Without aria-label, screen reader just says "button" -->
2<button>
3 <svg><!-- X icon --></svg>
4</button>
5
6<!-- With aria-label, screen reader says "Close dialog button" -->
7<button aria-label="Close dialog">
8 <svg><!-- X icon --></svg>
9</button>

Real-world shapes you've seen a hundred times:

JAVASCRIPT
1<button aria-label="Search">
2 <svg><!-- Magnifying glass icon --></svg>
3</button>
4
5<button aria-label="Add to cart">
6 <svg><!-- Shopping cart icon --></svg>
7</button>

One gotcha that trips candidates up: if an element has both visible text and aria-label, the screen reader reads only the aria-label. So don't double up without thinking.

aria-labelledby

Instead of duplicating a label, aria-labelledby points to existing text on the page via its id. That way you keep the sighted and screen-reader experiences in sync by design.

A dialog labelled by its heading:

JAVASCRIPT
1<div role="dialog" aria-labelledby="dialog-title">
2 <h2 id="dialog-title">Delete Account</h2>
3 <p>This action cannot be undone.</p>
4 <button>Delete</button>
5 <button>Cancel</button>
6</div>

No duplicate string to keep in sync. You can also reference multiple ids:

JAVASCRIPT
1<span id="first-name">First Name</span>
2<span id="required">(required)</span>
3<input aria-labelledby="first-name required" />

The screen reader reads them concatenated: "First Name (required)".

Interview framing: when asked for the difference between aria-label and aria-labelledby, the one-line answer is: aria-labelledby ties the accessible name to existing visible text, so updating the UI automatically updates the announcement.

aria-live

Now the interesting one. Imagine a client-side form that shows a validation error when the user types an invalid email. A sighted user sees the red message appear — but a screen reader user gets nothing unless you tell it to announce the change.

That's what aria-live does: it marks a region as "live" so screen readers notice updates.

Two values to know:

aria-live="polite" — announces when the user is idle. This is the default choice.

aria-live="assertive" — interrupts the user. Reserve it for genuinely urgent information like "Your session is about to expire."

A form-validation example:

JAVASCRIPT
1<form>
2 <label for="email">Email</label>
3 <input type="email" id="email" />
4
5 <!-- This div will announce changes to screen readers -->
6 <div aria-live="polite" role="status"></div>
7</form>
8
9<script>
10 const input = document.getElementById('email');
11 const status = document.querySelector('[aria-live]');
12
13 input.addEventListener('blur', () => {
14 if (!input.value.includes('@')) {
15 status.textContent = 'Please enter a valid email';
16 }
17 });
18</script>

When the text updates, the screen reader announces the error without the user having to hunt for it.

A loading-state example (this one is very common in interviews):

JAVASCRIPT
1<button id="submit">Submit</button>
2<div aria-live="polite">
3 <span id="status">Ready</span>
4</div>
5
6<script>
7 document
8 .getElementById('submit')
9 .addEventListener('click', async () => {
10 const status = document.getElementById('status');
11
12 status.textContent = 'Submitting...';
13 await submitForm();
14 status.textContent = 'Success! Form submitted.';
15 });
16</script>

Two companion attributes

aria-atomic — announce the whole region or just what changed?

JAVASCRIPT
1<!-- Announces "Items in cart: 4" (the whole thing) -->
2<div aria-live="polite" aria-atomic="true">
3 Items in cart: <span id="count">3</span>
4</div>
5
6<!-- Announces just "4" (only what changed) -->
7<div aria-live="polite" aria-atomic="false">
8 Items in cart: <span id="count">3</span>
9</div>

aria-relevant — which kinds of changes trigger an announcement?

JAVASCRIPT
1<!-- Only announce when text changes or nodes are added -->
2<div aria-live="polite" aria-relevant="additions text">
3 <!-- Updates here get announced -->
4</div>

A clean interview answer

aria-label: "Supplies an accessible name for elements without visible text — typical case is an icon-only button."

aria-labelledby: "References existing visible text by id. Better than aria-label because the visual and assistive experiences stay in sync automatically — e.g., using a dialog's heading as its accessible name."

aria-live: "Declares a live region so dynamic content gets announced. polite for most things; assertive only for urgent interruptions. Crucially, the container must exist in the DOM before you update it — otherwise nothing is announced."

Finished reading?

Mark this topic as solved to track your progress.