ARIA Basics
ARIA (Accessible Rich Internet Applications) is a set of HTML attributes that add extra accessibility information for assistive technology, mainly screen readers. It doesn’t change how anything looks or behaves for sighted, mouse-using visitors, only how it’s announced and navigated by assistive tech.
The first rule of ARIA: don’t use ARIA
If a semantic HTML element already does what you need, use it instead of recreating it with ARIA on a <div>. A real <button> gets keyboard support, focus handling, and the correct screen reader announcement automatically. A <div role="button"> gets none of that for free, you’d have to rebuild all of it yourself with JavaScript, and it’s easy to miss something.
<!-- Avoid: rebuilding a button badly -->
<div role="button" onclick="submit()">Submit</div>
<!-- Better: it already works -->
<button type="submit">Submit</button>
This is worth repeating because it’s the single most common ARIA mistake: adding role="button" to a <div> instead of just using <button>. See Semantic HTML
and Links: buttons vs links
before reaching for ARIA.
When ARIA is actually useful
ARIA earns its place when you’re building something HTML has no native element for, like a custom dropdown menu, a tabbed interface, or a live status message.
aria-label: naming an element with no visible text
Useful for icon-only buttons where there’s no text for a screen reader to read.
<button aria-label="Close dialog">
<svg aria-hidden="true">...</svg>
</button>
aria-hidden: hiding decorative content from screen readers
Hides an element from assistive technology while leaving it visible on screen. Use it for purely decorative icons or images, never on content someone actually needs.
<span aria-hidden="true">★</span> 4.8 out of 5
aria-expanded: state of a collapsible element
Tells a screen reader whether a dropdown, accordion, or menu is currently open.
<button aria-expanded="false" aria-controls="menu">Menu</button>
<ul id="menu" hidden>
<li><a href="/">Home</a></li>
</ul>
Your JavaScript needs to update aria-expanded to "true" when the menu opens, and back to "false" when it closes. ARIA attributes describe live state, they don’t update automatically.
aria-live: announcing dynamic changes
Tells a screen reader to announce content that changes without a page reload, like a form error or a “item added to cart” confirmation.
<div aria-live="polite" id="status"></div>
document.getElementById("status").textContent = "Item added to cart";
polite waits for the user to pause before announcing. assertive interrupts immediately, reserve it for urgent, time-sensitive messages, it’s disruptive if overused.
Common mistakes
- Adding
role="button"to a<div>instead of using<button>. - Setting
aria-hidden="true"on an element that still contains focusable content, like a link, leaving a keyboard-focusable element that screen readers skip entirely, which is confusing. - Adding ARIA attributes and never updating them with JavaScript, so
aria-expanded="false"stays stuck even after the menu opens. - Overusing
aria-labelon elements that already have clear visible text; a redundantaria-labelcan override, rather than supplement, what’s already there.
FAQ
Does adding ARIA attributes make my site accessible?
No. ARIA is one tool among many. Accessibility comes first from correct semantic HTML, sufficient colour contrast, keyboard support, and readable content. ARIA fills specific gaps, it isn’t a fix applied on top of otherwise inaccessible markup.
How do I know if I’m using ARIA correctly?
Test with an actual screen reader (VoiceOver on Mac, NVDA on Windows are free) and keyboard-only navigation. Automated tools like axe DevTools catch some ARIA misuse, but manual testing catches far more.
What to read next
- Semantic HTML : the elements to reach for before ARIA
- Page Landmarks : landmark roles that come from semantic HTML, not ARIA
- Best Practices Checklist : a quick reference for shipping accessible HTML