Accessibility

What are ARIA (Accessible Rich Internet Applications) roles?

ARIA fills the gap between what HTML can express and what your UI actually does. When you build custom components — tabs, modals, accordions, live feeds —...

13 Mar 2024

What are ARIA (Accessible Rich Internet Applications) roles?

ARIA fills the gap between what HTML can express and what your UI actually does. When you build custom components — tabs, modals, accordions, live feeds — native HTML elements don't exist for those patterns. Screen readers see a <div> and have no idea it behaves like a button. ARIA gives you the vocabulary to fix that.

Think of ARIA as metadata for assistive technology. It doesn't change how the element looks or behaves for sighted users. It tells screen readers what something is, what state it's in, and how elements relate to each other.

The most useful roles and attributes

role="button" — Tells assistive tech that a non-button element acts like a button. Use this when you can't use a native <button> (which you should prefer when possible).

Html
<div role="button" tabindex="0" onclick="handleButtonClick()">Click me</div>

role="link" — Same idea, but for elements that behave like hyperlinks without being <a> tags.

Html
<div role="link" tabindex="0" onclick="handleLinkClick()">Learn more</div>

aria-label — Gives an element a text label when the visible text isn't descriptive enough. The close button below has visible text "X" — meaningless without context.

Html
<button aria-label="Close modal" onclick="closeModal()">X</button>

aria-labelledby — Points to another element's ID to use as a label. Useful when the label already exists on the page.

Html
<div id="modalTitle">Modal Title</div>
<div role="dialog" aria-labelledby="modalTitle">...</div>

aria-describedby — Links an element to supplementary text. Not the label — the extra context.

Html
<input type="password" aria-describedby="passwordHelpBlock">
<div id="passwordHelpBlock">Password must be at least 8 characters long</div>

aria-expanded — Communicates whether a collapsible section is open or closed. Essential for accordions, dropdowns, and tree views.

Html
<button aria-expanded="false" aria-controls="collapseContent" onclick="toggleCollapse()">Toggle content</button>
<div id="collapseContent" hidden>...</div>

aria-live — Marks a region whose content updates dynamically. Screen readers announce changes as they happen. Use "polite" for non-urgent updates, "assertive" for critical ones.

Html
<div aria-live="assertive" id="liveRegion">New message received</div>

The trade-off

ARIA is powerful, but it's also easy to misuse. The first rule of ARIA is literally "don't use ARIA" — if a native HTML element does the job, prefer it. A <button> is always better than <div role="button"> because native elements come with keyboard handling, focus management, and correct semantics for free.

ARIA adds no behavior. It only adds meaning. If you set role="button" but forget to handle Enter and Space key events, keyboard users can't activate it. You get the label without the functionality.

Use ARIA to enhance, not to replace. Get the native HTML right first, then layer ARIA on top for the custom parts.

Keep reading