DEV Community

AgentKit
AgentKit

Posted on

ARIA Labels Are Probably Making Your Site Less Accessible. Here's When to Use Them (And When to Delete Them).

There's a rule in the ARIA specification that most developers never read. It's the first rule, literally called "The First Rule of ARIA Use," and it says: don't use ARIA if you can use a native HTML element instead.

I bring this up because I've been reviewing a lot of accessibility remediation work lately, and I keep seeing the same pattern. A team gets flagged for accessibility issues, someone Googles "how to make accessible," and they start sprinkling ARIA attributes everywhere like hot sauce. More ARIA must mean more accessible, right?

No. Often it means less accessible. Let me show you what I mean.

The problem with redundant ARIA

Here's something I found on a real production site last month:

<button role="button" aria-label="Submit form" aria-roledescription="button">
  Submit form
</button>
Enter fullscreen mode Exit fullscreen mode

Every single ARIA attribute on this element is unnecessary. The <button> element already has an implicit role of "button." The visible text "Submit form" already serves as its accessible name. And aria-roledescription is overriding the browser's perfectly good native role description with... the same thing.

This isn't harmless. When you add aria-label to an element that already has visible text content, some screen readers will announce the ARIA label instead of the visible text. If those two ever get out of sync -- and they will, because developers update visible text without thinking about the aria-label -- you end up with sighted users seeing one thing and screen reader users hearing something completely different.

I've seen a navigation link that visually said "Pricing" but whose aria-label still said "View our plans and pricing information." That's not just verbose -- it's confusing when someone asks you "click the link that says Pricing" and your screen reader has been calling it something else entirely.

When aria-label actually causes harm

The redundancy problem is annoying, but the real damage happens when ARIA overrides correct semantics.

Consider this pattern I see constantly in React component libraries:

<a href="/dashboard" role="button" aria-label="Go to dashboard">
  Dashboard
</a>
Enter fullscreen mode Exit fullscreen mode

This link has been forced into acting like a button. A screen reader will announce it as "Go to dashboard, button." But it's not a button. It navigates to a new page. Users who hear "button" expect an action on the current page. Users who hear "link" know they're going somewhere new. That distinction matters for orientation, and the ARIA attributes are actively lying about it.

The fix here isn't adding more ARIA. It's removing it:

<a href="/dashboard">Dashboard</a>
Enter fullscreen mode Exit fullscreen mode

That's it. The browser handles the rest. The screen reader announces "Dashboard, link." The user knows exactly what will happen.

The icon button exception

Now, there absolutely are cases where ARIA is the right tool. The most common legitimate use case is icon-only buttons. If a button contains nothing but an SVG icon and no visible text, assistive technology has no way to determine its purpose without help.

<!-- Bad: screen reader says "button" with no label -->
<button>
  <svg viewBox="0 0 24 24"><!-- magnifying glass icon --></svg>
</button>

<!-- Good: screen reader says "Search, button" -->
<button aria-label="Search">
  <svg aria-hidden="true" viewBox="0 0 24 24"><!-- magnifying glass icon --></svg>
</button>
Enter fullscreen mode Exit fullscreen mode

Notice two things here. First, aria-label provides the accessible name that the visible content can't. Second, aria-hidden="true" on the SVG prevents screen readers from trying to announce the SVG markup itself, which usually comes out as gibberish.

This is ARIA doing what it was designed to do: filling a gap that HTML alone can't fill.

Another legitimate case: live regions

If part of your page updates dynamically without a full page reload -- a notification toast, a form validation message, a chat feed -- screen readers won't announce the change unless you tell them to. This is where aria-live is genuinely essential.

<div aria-live="polite" aria-atomic="true">
  <!-- Content injected by JavaScript -->
</div>
Enter fullscreen mode Exit fullscreen mode

When content inside this container changes, screen readers will announce the update at the next pause in their reading. There's no HTML equivalent for this behavior. ARIA is the only way to achieve it.

The mistake I see here is using aria-live="assertive" everywhere. "Assertive" interrupts whatever the screen reader is currently saying. It's the accessibility equivalent of a JavaScript alert() -- use it for genuinely urgent messages only. For most updates, "polite" is correct.

The decision framework I actually use

When I'm auditing a component and trying to decide whether ARIA attributes belong, I run through three questions in order.

First: does a native HTML element already express this semantics? If yes, use that element and delete the ARIA. A <nav> is better than <div role="navigation">. A <button> is better than <div role="button" tabindex="0" onkeydown="...">. Native elements come with keyboard handling, focus management, and form participation built in. ARIA gives you none of that -- it only changes what the accessibility tree reports, not how the element actually behaves.

Second: does the element have visible text that already serves as its accessible name? If yes, don't add aria-label. You're creating a maintenance burden and a potential mismatch for no gain. The one exception is when the visible text is ambiguous in context -- for instance, multiple "Read more" links on a page where each needs to be distinguishable. In that case, aria-label="Read more about pricing plans" adds genuine value.

Third: is this a pattern that simply can't be expressed in HTML alone? Custom comboboxes, tree views, tab panels, live regions -- these are real ARIA use cases. If you're building a complex widget that has no native HTML equivalent, ARIA is the right approach. But even then, start with the WAI-ARIA Authoring Practices patterns. Don't invent your own role combinations.

What to do right now

If you've been adding ARIA attributes to make automated accessibility checkers happy, go back and audit those additions. Automated tools flag missing accessible names, and aria-label makes the warning disappear, but that doesn't mean it was the right fix.

Open your browser's accessibility inspector (Chrome DevTools has one under the Elements panel, look for the Accessibility tab). Check a few key components. If the accessibility tree shows names and roles that already match the visible content, the ARIA attributes are redundant. Delete them.

I know this feels counterintuitive. Deleting accessibility-related code to improve accessibility seems wrong. But the ARIA spec authors put that first rule at the top for a reason. The most accessible code is usually the simplest code -- native HTML elements, visible labels, semantic structure.

If you want a systematic way to audit your ARIA usage alongside other EAA compliance requirements, I maintain a free checklist at agentkit.kit.com that includes an ARIA review section. It won't just help you find problems -- it'll help you figure out which ARIA to keep and which to throw away.

Top comments (0)