ARIA Roles and Labels
Fill accessibility gaps that native HTML can't express on its own.
ARIA (Accessible Rich Internet Applications) is a set of attributes that describe roles, states, and labels to assistive technology. It's powerful — and easy to misuse.
The first rule of ARIA
The official first rule is: don't use ARIA if a native element already does the job. A real <button> beats <div role="button"> every time, because the native element brings focus, keyboard, and semantics for free. Reach for ARIA only to fill genuine gaps.
The attributes you'll actually use
aria-label— gives an element an accessible name when there's no visible text (think an icon-only button).aria-labelledby— names an element by pointing at theidof visible text.aria-describedby— links to extra descriptive text, like a hint under a field.aria-live— announces content that changes dynamically, such as a status message.aria-hidden="true"— hides decorative content from screen readers.
<button aria-label="Close dialog">×</button>That single label turns a meaningless × into a button a blind user can understand.
Example
When to use it
- A developer adds aria-label="Close dialog" to an icon-only X button so screen reader users know its purpose.
- A custom dropdown menu uses role="listbox" and role="option" with aria-selected so assistive technology treats it as a native select.
- A loading spinner uses aria-live="polite" so screen readers announce when an async operation completes.
More examples
Aria-label for an icon button
aria-label provides an accessible name when visible text is absent; aria-hidden hides the decorative SVG.
<button aria-label="Close notification">
<svg aria-hidden="true" focusable="false" width="16" height="16">
<line x1="0" y1="0" x2="16" y2="16" stroke="currentColor">
<line x1="16" y1="0" x2="0" y2="16" stroke="currentColor">
</svg>
</button>Live region for status updates
role="status" with aria-live="polite" announces dynamic content changes to screen readers without moving focus.
<div role="status" aria-live="polite" aria-atomic="true" id="status">
<!-- Updated dynamically by JS -->
</div>
<button onclick="document.getElementById('status').textContent='File saved successfully.'">
Save
</button>Aria-expanded for accordion toggle
aria-expanded signals the open/closed state of the controlled panel to screen reader users.
<button
aria-expanded="false"
aria-controls="panel-1"
id="btn-1"
onclick="
const btn = this;
const open = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', !open);
document.getElementById('panel-1').hidden = open;
">
Show details
</button>
<div id="panel-1" hidden>
<p>Expanded content goes here.</p>
</div>
Discussion