Welcome to ARIA essentials, a quick-start guide to the attributes that make rich web apps work for assistive technology users.
Accessible Rich Internet Applications, abbreviated as ARIA, is a set of attributes defined by the W3C in the WAI-ARIA 1.2 specification that can be added to HTML elements. These attributes give assistive technologies, such as screen readers, extra information about what an element is, what state it is in and how it relates to other elements. ARIA changes what assistive technology announces. It does not change how an element looks or behaves.
The Purpose:
ARIA bridges the gap between dynamic web content and the limits of plain HTML. When you build something HTML has no element for, such as a tab panel or a combobox, ARIA lets you describe it to a screen reader so the user knows what it is and how to operate it. It helps people with visual, cognitive and motor disabilities who rely on assistive technology to understand the structure and behaviour of a page.
The First Rule of ARIA: No ARIA Is Better Than Bad ARIA
Before you write a single ARIA attribute, learn the first rule from the W3C’s Using ARIA guide: if a native HTML element or attribute already has the semantics and behaviour you need, use it instead of adding ARIA. A real <button> is focusable, works with Enter and Space and is announced as a button, all for free. A <div role="button"> only gets the announcement; you have to add the rest yourself.
The ARIA Authoring Practices Guide puts it bluntly in its Read Me First page: no ARIA is better than bad ARIA. A role is a promise. When you say an element is a slider, screen reader users expect it to behave like one, and if it does not, you have made the page harder to use, not easier. The W3C’s ARIA in HTML specification lists which roles and attributes are allowed on each HTML element, which is the quickest way to check you are not overriding native semantics.
ARIA Roles and Properties: Decoding the Language of Accessibility
Roles:
ARIA introduces roles that define the type of user interface component an element represents. Roles range from simple ones like “button” or “link” to complex structures such as “alert” or “tablist,” giving assistive technologies the semantics they need to describe a component.
Example:
<button type="button" aria-label="Add to cart">🛒</button>
Here the native button element already has the button role, so no role attribute is needed. The aria-label attribute gives the icon-only button an accessible name, so a screen reader announces “Add to cart, button” instead of an emoji. Our guide to aria-label covers when to use it, and the aria-labelledby guide covers naming an element from visible text.
States and Properties:
ARIA states and properties add details about an element’s current condition or value. For example, aria-checked tells assistive technology whether a custom checkbox is checked, and aria-expanded tells it whether a menu or accordion is open.
Example: use the native checkbox
<input type="checkbox" id="subscribe" checked> <label for="subscribe">Subscribe to newsletter</label>
A native checkbox already reports its checked state, so it needs no ARIA at all. Adding aria-checked to it can only create a mismatch between what the browser knows and what you told it.
Example: a custom checkbox
<div role="checkbox" aria-checked="false" tabindex="0" aria-labelledby="sub-label"></div> <span id="sub-label">Subscribe to newsletter</span>
If you genuinely need a custom control, aria-checked belongs on the element with role="checkbox". You also have to add tabindex="0" so it can receive focus, toggle aria-checked between “true” and “false” in JavaScript, and make the Space key toggle it, just as the native control does. For disclosure widgets, our aria-expanded guide walks through the same idea.
ARIA in Action: Three Quick-Start Patterns
The ARIA Authoring Practices Guide (APG) documents tested patterns for common widgets. Here are simplified versions of three you will use most.
1. Live Regions for Dynamic Updates:
When content changes without a page reload, such as a cart total or a “saved” message, screen readers do not notice unless you tell them. A live region does that.
Example:
<div id="cart-status" role="status"></div>
<script>
document.getElementById('cart-status').textContent = 'Item added to cart';
</script>
role="status" is a polite live region: the screen reader waits until the user pauses before reading the new text. Put the empty container in the page first and change its text later; a live region added at the same moment as its message is often not announced. Reserve role="alert" (which is assertive and interrupts the user) for urgent problems such as a failed payment. Do not combine role="status" with aria-live="assertive"; the two contradict each other.
2. A Disclosure Navigation Menu:
Most site navigation menus are best built as a disclosure: a button that shows and hides a list of links. This is simpler and more robust than the full ARIA menu role, which is meant for application menus like those in a desktop program.
Example:
<nav aria-label="Main">
<button type="button" aria-expanded="false" aria-controls="products-menu">Products</button>
<ul id="products-menu" hidden>
<li><a href="/audits/">Audits</a></li>
<li><a href="/training/">Training</a></li>
</ul>
</nav>
<script>
const btn = document.querySelector('[aria-controls="products-menu"]');
const menu = document.getElementById('products-menu');
btn.addEventListener('click', () => {
const open = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', String(!open));
menu.hidden = open;
});
</script>
The button is native, so it works with the keyboard already. aria-expanded tells screen reader users whether the list is open, and the links inside are ordinary links reached with Tab. The APG disclosure pattern has a full navigation example.
3. A Modal Dialog:
The easiest accessible modal is the native <dialog> element opened with showModal(). The browser moves focus into the dialog, makes the rest of the page inert and closes it on Escape.
Example:
<button type="button" id="open">Delete account</button>
<dialog id="confirm" aria-labelledby="confirm-title">
<h2 id="confirm-title">Delete your account?</h2>
<p>This cannot be undone.</p>
<button type="button" id="cancel">Cancel</button>
<button type="button" id="delete">Delete</button>
</dialog>
<script>
const dialog = document.getElementById('confirm');
document.getElementById('open').addEventListener('click', () => dialog.showModal());
document.getElementById('cancel').addEventListener('click', () => dialog.close());
</script>
The only ARIA here is aria-labelledby, which gives the dialog its accessible name from the heading. If you have to build a modal from a div, follow the APG modal dialog pattern: add role="dialog" and aria-modal="true", move focus in when it opens, keep Tab inside it, close it on Escape and return focus to the trigger. Our article on the HTML inert attribute explains how to lock the background.
Keyboard Support Is Your Job, Not ARIA’s
A common misunderstanding is that ARIA makes things keyboard accessible. It does not. ARIA only changes what assistive technology announces; it adds no focus, no key handling and no behaviour. If you give a div a role, you also have to make it focusable and write the keyboard interaction yourself. That is why native elements come first.
Example: a custom slider, done properly
<span id="vol-label">Volume</span>
<div role="slider" tabindex="0" aria-labelledby="vol-label"
aria-valuemin="0" aria-valuemax="100" aria-valuenow="50"></div>
The role and the value attributes are only half the work. The slider also needs an accessible name (here from aria-labelledby), and JavaScript that changes the value with the arrow keys, Home and End, and updates aria-valuenow each time. The APG slider pattern lists the required keys. In most forms, a native <input type="range"> gives you all of this for free. Our guide to manual keyboard accessibility testing shows how to check custom widgets.
ARIA and SEO: Keep Expectations Realistic
ARIA is written for assistive technology, not for search engines, and there is no evidence that adding ARIA attributes improves rankings. What does help both groups is good native HTML: real headings, landmarks such as <nav> and <main>, descriptive link text and proper page structure. Build that first, use ARIA only to fill genuine gaps, and treat any SEO benefit as a side effect of a clearer page.
Five Common ARIA Mistakes to Avoid
- Redundant roles.
<button role="button">or<nav role="navigation">add nothing. Native elements already expose these roles. - Hiding focusable content.
aria-hidden="true"on an element that contains links or buttons leaves keyboard users tabbing into things a screen reader cannot see. Usehiddenorinertinstead. - Labels that contradict the screen. An
aria-labelthat differs from the visible text breaks voice control users, who say what they see. Start the accessible name with the visible label. - Using the menu role for site navigation.
role="menu"tells screen readers to expect arrow-key behaviour like a desktop app. For a list of links, a disclosure button and a plain list are clearer. - Setting a state once and never updating it. An accordion that always says
aria-expanded="false"is giving wrong information every time it opens.
Each of these is easy to spot with a quick keyboard and screen reader pass, and most are flagged by automated checkers.
ARIA Essentials Best Practices: Integrating ARIA Seamlessly
Native Semantics First:
Use native HTML elements whenever they exist. ARIA should fill gaps, not replace elements that already work.
Contextual Application:
Apply ARIA only where it genuinely adds information. Overuse or misuse, such as a role that contradicts the element or a state that is never updated, confuses screen reader users. The W3C’s ARIA basics page is a good refresher.
Keep States in Sync:
If you set aria-expanded, aria-checked or aria-valuenow, update it every time the component changes. A stale state is worse than none.
Regular Testing:
Test with a keyboard and at least one screen reader, and run an automated checker to catch invalid attributes. Our guides to screen reader testing and automated accessibility testing explain what each method catches. ARIA mistakes usually show up as failures of WCAG 4.1.2 Name, Role, Value.
For a comprehensive understanding of accessibility testing tools and to make manual testing easy, consider exploring our Accessibility Tools hub. WebAIM’s ARIA guide is another clear, practical reference.
Conclusion: ARIA as the Beacon of Inclusive Digital Experiences
ARIA is a powerful tool when you use it sparingly: native HTML first, ARIA to describe what HTML cannot, and keyboard behaviour written to match every role you add. Get those three right and your menus, dialogs and live updates will make sense to everyone, including people who never see the screen.
Remember, the pursuit of web accessibility isn’t just a legal or moral imperative. It’s a commitment to a digital world where every interaction is an opportunity for connection, understanding, and empowerment.
Ready to go further? Read our deeper guide to ARIA attributes. If you want an expert to check your components, our accessibility audit services test ARIA patterns with real assistive technology, and our accessibility remediation team can fix what we find, including in React applications. You can also reach out to us with questions.