ARIA: when to use it and when it's doing more harm than good
ARIA attributes can make inaccessible interfaces accessible. They can also make accessible interfaces inaccessible. The first rule of ARIA is not to use it.
The first rule of ARIA is: don't use ARIA. This isn't a joke or a paradox. It's the actual opening principle from the WAI-ARIA Authoring Practices Guide, and it exists because ARIA is routinely used to fix problems that native HTML would have prevented. When teams reach for ARIA before exhausting native elements, they often add complexity that the browser doesn't need to infer and that assistive technology doesn't need to translate.
ARIA changes what the accessibility tree says about an element. It doesn't change the element's behavior. That gap between announcement and behavior is where most ARIA bugs live.
What ARIA can and can't do
A <div> with role="button" will be announced as a button by a screen reader. What it won't do: receive focus by keyboard without a tabindex, activate on Enter or Space without a keydown handler, respond to pointer events the way a real button does, or surface its disabled state correctly without additional ARIA. The native <button> gives you all of that for free. The ARIA approach requires you to rebuild it piece by piece, and each piece you forget is a gap.
This is the diagnostic test for any ARIA usage: what would happen if we used the native HTML element instead? If the answer is "that would work," then the ARIA is papering over a structural decision that should be revisited. If the answer is "native HTML can't express this pattern" (a custom combobox, a tree widget, a live region), then ARIA is doing real work.
The cases where ARIA is doing real work are narrower than most codebases assume. They're mostly interactive patterns that don't have a native equivalent and dynamic content that needs to be announced without moving focus.
The overuse patterns I see most often
aria-label on elements that already have text. A button that reads "Save changes" doesn't need aria-label="Save changes". A button that reads "Save" but needs to announce "Save changes to your profile" might justify it, but that decision is usually a sign the visible text should be reconsidered, not papered over with a hidden label. Adding aria-label overrides the visible text, so the screen reader user hears something different from what's on screen. That discrepancy makes support conversations awkward.
role="presentation" and aria-hidden="true" on things that don't need hiding. These attributes are correct when an element is genuinely decorative: a separator icon, a repeated design flourish, a chart's axis lines when the chart has a proper table alternative. They're wrong when applied to content that provides meaning and is simply not visible in a way the developer expected the screen reader to announce. Audits find aria-hidden on error messages, on required-field indicators, on status text.
aria-required instead of the native required attribute. If an input is genuinely required, the HTML required attribute handles the announcement, triggers native browser validation, and signals the form constraint to the accessibility tree. aria-required alone does two of those three things and is correctly used when you're suppressing native validation but still want the semantic. Most of the time you're not suppressing native validation.
aria-expanded on things that don't expand. I've found this in production on buttons that trigger a page navigation, on checkboxes, on icons. aria-expanded communicates that the element controls a collapsible region: specifically, that a region exists and is currently open or closed. Applying it to an element that doesn't control a disclosed region confuses screen reader users who expect to hear the associated region change state.
When ARIA is the right answer
Custom interactive widgets. If you build a tab panel using <div> elements because the visual design doesn't work with native <select> or a set of radio buttons, you need role="tablist", role="tab", role="tabpanel", aria-selected, aria-controls. The ARIA Authoring Practices Guide has patterns for tabs, trees, comboboxes, menu buttons, and most complex widgets. Following those patterns exactly, including the keyboard interaction requirements, produces interfaces that work with assistive technology. Deviating from them produces interfaces that partially work.
Live regions. When content changes on the page without a focus change, screen readers won't announce it unless you've told them to. aria-live="polite" for asynchronous updates, filter results, or success confirmations. aria-live="assertive" only for urgent interruptions, like error states that need immediate attention. The region needs to be in the DOM before the content changes; injecting the element at announcement time doesn't reliably trigger the announcement.
Complementing native elements when native semantics aren't enough. aria-describedby to associate a hint or error message with an input. aria-invalid paired with an error message that explains what's wrong. aria-label on an icon-only button when the visual context makes the label obvious but no visible text exists. These are ARIA working as intended: filling a gap that the native element can't fill on its own.
How to audit your own ARIA usage
The quickest check: open your browser DevTools accessibility tree and read the element list without looking at the page. Each element should announce a role, a name, and a state that accurately describes what it is and what it does. If you find an element that announces a role that doesn't match its behavior, or a state that never changes, or a name that differs from the visible label, you've found an ARIA problem.
The second check: can you remove this ARIA attribute and replace it with a semantic HTML element? If yes, do that instead.
The common thread in ARIA overuse is well-intentioned engineers adding attributes to pass automated audits. Automated scanners flag "button with no label." The fix looks like adding aria-label. The correct fix is to add visible text or to use a button that already has visible text, but that might require a conversation with design. The ARIA fix is faster and passes the scanner. It also creates a maintenance burden: now two pieces of content (visible text and ARIA label) can drift apart on every future edit.
ARIA is a repair tool. It was designed to describe things that HTML can't describe on its own. Using it to describe things that HTML already describes correctly just adds noise to the accessibility tree, and assistive technology has to work through that noise to reach the user.
Be the first to rate this article.
Let's work together.
Open to select projects and collaborations — design systems, accessibility, and AI-native product work.