Accessibility Fix Guide

How to Use ARIA Labels Correctly Without Creating Accessibility Bugs

ARIA can improve accessibility when HTML alone cannot express a component's name, role, state, or relationship. But ARIA can also make accessibility worse when it is used as a shortcut, added without testing, or used to override meaningful visible text. The attributes you reach for most often — aria-label, aria-labelledby, and aria-describedby — are powerful but easy to misuse.

One of the most common ARIA tools is aria-label. It gives an element an accessible name when there is no visible text. For example, an icon-only menu button can use aria-label="Open menu" so a screen reader announces the button clearly.

<button type="button" aria-label="Open menu">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

That is a good use case. The button has no visible text, so the ARIA label provides a name. But aria-label is often overused. Developers add it to links that already have text. They use it to hide vague visible labels. They use it when a real <label> would be better. They create names that disagree with what sighted users see. They add ARIA to non-semantic elements instead of fixing the HTML.

ARIA is powerful, but the first rule is simple: use native HTML whenever possible. Add ARIA only when it improves the experience and can be tested. ADA CodeFix flags ARIA label issues because incorrect ARIA can create confusing or misleading experiences for assistive technology users. This guide explains when to use aria-label, when to use aria-labelledby, when to use aria-describedby, and how to avoid common ARIA mistakes.

This page is informational and is not legal advice. Accessibility requirements can vary by site, organization, and jurisdiction. For legal guidance, consult qualified counsel. For accessibility conformance, combine automated scans with manual keyboard and screen reader testing.

What aria-label does

aria-label gives an element an accessible name.

<button type="button" aria-label="Close dialog">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

A screen reader can announce this as "Close dialog, button." Without the label, the button might be announced only as "button," which is not useful.

aria-label is most useful when:

aria-label vs aria-labelledby vs aria-describedby

aria-label provides a text name directly on the element.

<button aria-label="Close dialog">...</button>

aria-labelledby points to visible text elsewhere on the page and uses that text as the accessible name.

<h2 id="billing-heading">Billing address</h2>

<section aria-labelledby="billing-heading">
  ...
</section>

In many cases, aria-labelledby is better because it uses visible text. That keeps the experience consistent for sighted users and screen reader users.

aria-describedby provides an accessible description, not the main name.

<label for="password">Password</label>
<p id="password-help">Use at least 12 characters.</p>
<input
  id="password"
  type="password"
  aria-describedby="password-help"
>

The label is still "Password." The description adds helpful context. Use aria-describedby for help text, error messages, format requirements, and extra instructions.

ARIA and WCAG

The most relevant WCAG criterion is 4.1.2 Name, Role, Value. User interface components need a name and role that assistive technology can understand. ARIA labels often affect the accessible name, so misusing them can directly cause a 4.1.2 failure.

ARIA can also relate to form labels, button names, link purpose, error messages, modal dialogs, menus, tabs, accordions, and custom widgets. Correct ARIA can make a custom component understandable. Incorrect ARIA can hide useful text, create misleading names, or expose the wrong role. WCAG 1.3.1 Info and Relationships is also relevant because programmatic relationships, including those expressed through ARIA, should match what users perceive visually.

Good use cases for aria-label

Icon-only buttons

<button type="button" aria-label="Open navigation menu">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

Search input without visible label

A visible label is usually better, but an ARIA label can work when the design requires it.

<input type="search" aria-label="Search articles">

A visually hidden label may be better:

<label for="article-search" class="sr-only">Search articles</label>
<input id="article-search" type="search">

Close buttons

<button type="button" aria-label="Close modal">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

Region labels

<nav aria-label="Primary navigation">
  ...
</nav>

<nav aria-label="Footer navigation">
  ...
</nav>

This helps distinguish multiple navigation regions so screen reader users can move between them.

Bad uses of aria-label

Bad use 1: Overriding visible link text incorrectly

Problem:

<a href="/pricing" aria-label="Start free scan">
  Pricing
</a>

Sighted users see "Pricing," but screen reader users hear "Start free scan." That creates inconsistent expectations and can violate the WCAG requirement that the accessible name should contain the visible label.

Better:

<a href="/pricing">Pricing</a>

Or:

<a href="/pricing">Compare plans and pricing</a>

Bad use 2: Replacing a real form label

Problem:

<input type="email" aria-label="Email address">

This can be acceptable in limited cases, but a visible label is usually better. Visible labels help everyone, including people with cognitive disabilities and users who rely on visual cues.

Better:

<label for="email">Email address</label>
<input id="email" type="email" autocomplete="email">

Bad use 3: Adding ARIA to non-interactive elements instead of fixing HTML

Problem:

<div role="button" tabindex="0" aria-label="Submit form">
  Submit
</div>

Better:

<button type="submit">
  Submit
</button>

Native HTML is simpler and more reliable. It provides the role, keyboard behavior, and focus handling for free.

Bad use 4: Empty or vague ARIA labels

Problem:

<button type="button" aria-label="">
  <svg aria-hidden="true">...</svg>
</button>

Problem:

<button type="button" aria-label="button">
  <svg aria-hidden="true">...</svg>
</button>

Better:

<button type="button" aria-label="Delete saved report">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

Bad use 5: Hiding useful visible text with ARIA

If you add aria-label, it can override the visible text as the accessible name.

Problem:

<button aria-label="Submit">
  Delete account
</button>

This is dangerous. A screen reader user may hear "Submit" while sighted users see "Delete account." Voice users who say "click Delete account" may not be able to activate the button.

Better:

<button>
  Delete account
</button>

aria-labelledby examples

Modal dialog title

<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="scan-dialog-title"
>
  <h2 id="scan-dialog-title">Start accessibility scan</h2>
  ...
</div>

The dialog name comes from the visible heading. Sighted users and screen reader users get the same name.

Form group

<div role="group" aria-labelledby="notification-heading">
  <h3 id="notification-heading">Notification preferences</h3>

  <label>
    <input type="checkbox" name="email-updates">
    Email updates
  </label>

  <label>
    <input type="checkbox" name="sms-updates">
    SMS updates
  </label>
</div>

For radio groups, prefer fieldset and legend when possible.

aria-describedby examples

Help text

<label for="url">Website URL</label>
<p id="url-help">Enter the public page you want to scan.</p>
<input
  id="url"
  type="url"
  aria-describedby="url-help"
>

Error messages

<label for="email">Email address</label>
<input
  id="email"
  type="email"
  aria-invalid="true"
  aria-describedby="email-error"
>
<p id="email-error">Enter a valid email address.</p>

Multiple descriptions

<label for="password">Password</label>
<p id="password-help">Use at least 12 characters.</p>
<p id="password-error">Password is too short.</p>
<input
  id="password"
  type="password"
  aria-invalid="true"
  aria-describedby="password-help password-error"
>

Multiple IDs can be referenced in a single aria-describedby by separating them with spaces.

Accessible name priority

Accessible name calculation can be complex, but a practical rule is:

Because aria-label can override visible text, use it carefully. When a control has visible text, prefer to leave it as the accessible name unless you have a very specific reason to override it.

How to fix ARIA label issues step by step

Step 1: Check whether native HTML solves the problem

Before adding ARIA, ask whether the correct HTML element would solve it.

Instead of:

<div role="button" aria-label="Save changes" tabindex="0">
  Save
</div>

Use:

<button type="button">
  Save changes
</button>

Step 2: Prefer visible labels

If users need to understand a control, visible text is usually best.

<label for="company">Company name</label>
<input id="company" type="text">

Step 3: Use visually hidden text when design needs it

<button type="button">
  <svg aria-hidden="true" focusable="false">...</svg>
  <span class="sr-only">Open menu</span>
</button>

This can be easier to maintain than aria-label because the text exists in the DOM and can be inspected and translated like normal content.

Step 4: Use aria-label for truly unlabeled icon controls

<button type="button" aria-label="Download report">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

Step 5: Use aria-labelledby when visible text already exists

<h2 id="filters-title">Filter reports</h2>
<div role="region" aria-labelledby="filters-title">
  ...
</div>

Step 6: Use aria-describedby for extra context

Do not cram instructions into aria-label. Use aria-describedby instead.

<label for="scan-url">Page URL</label>
<p id="scan-url-help">Use the full URL, including https://.</p>
<input id="scan-url" type="url" aria-describedby="scan-url-help">

How ADA CodeFix detects ARIA label issues

ADA CodeFix can flag issues such as:

Automated tools can find many ARIA problems, especially broken references and missing names. Developers should still test the final experience with assistive technology, because automated tools cannot judge whether a label is meaningful in context.

Manual ARIA review checklist

Use this checklist after changing or adding ARIA.

  1. Is ARIA necessary, or would native HTML be better?
  2. Does every interactive control have a clear accessible name?
  3. Does the accessible name match or support visible text?
  4. Are icon-only buttons labeled?
  5. Are aria-labelledby references valid?
  6. Are aria-describedby references valid?
  7. Is help text used as a description, not as a label replacement?
  8. Are form fields visibly labeled where possible?
  9. Are region labels unique when multiple regions exist?
  10. Are ARIA states updated when the UI changes?
  11. Has the component been tested by keyboard?
  12. Has the accessible name been checked in browser dev tools or a screen reader?

Common mistakes to avoid

Mistake 1: Using ARIA first

ARIA should not be the first solution. Start with correct HTML. A real button, a, label, or nav element solves most problems without any ARIA at all.

Mistake 2: Overriding visible text

Do not create one label for sighted users and a different label for screen reader users unless there is a very specific reason. This breaks expectations and can also block voice-control users who try to activate controls by their visible name.

Mistake 3: Broken references

If aria-labelledby="dialog-title" points to an element that does not exist, the name may fail. The same applies to aria-describedby. Always confirm that referenced IDs match real elements in the DOM.

Mistake 4: Duplicate region labels

Multiple nav aria-label="Navigation" regions are less helpful than specific labels like "Primary navigation" and "Footer navigation." Distinct labels help screen reader users jump between landmarks.

Mistake 5: Static ARIA states

If a menu button says aria-expanded="false" even when the menu is open, the ARIA is misleading. Make sure your code updates ARIA state attributes whenever the UI state changes.

Platform-specific notes

WordPress

Plugins may add ARIA automatically. Check whether labels are accurate, references exist, and menu states update correctly. Theme menus, mobile toggles, and search forms are common places where ARIA gets out of sync with visible state.

Shopify

Review cart, search, account, menu, and filter icons. Many Shopify themes use icon-only controls that need accessible names. Cart drawers and quick-view modals often need both a dialog name and labeled close buttons.

Webflow

Custom interactions may require ARIA states, but do not add ARIA without testing. Make sure toggle states update when panels open or close, and that any ARIA reference IDs survive any symbol or component duplication.

React and Next.js

Component libraries should make accessible names required for icon-only components.

function IconButton({ label, children, ...props }) {
  if (!label) {
    throw new Error("IconButton requires an accessible label.");
  }

  return (
    <button type="button" aria-label={label} {...props}>
      {children}
    </button>
  );
}

Patterns like this push accessibility into the component contract, so a missing label fails loudly during development instead of silently shipping to users.

Final takeaway

ARIA labels are useful when they solve a real naming problem. They are risky when they are used to cover up poor HTML, override visible text, or create labels that cannot be verified by users. The best approach is to start with native HTML, use visible labels whenever possible, use aria-labelledby when visible text already exists, use aria-describedby for help and error text, and reserve aria-label for controls that truly need an accessible name without visible text.

ADA CodeFix can help find ARIA naming issues and broken references, but ARIA changes should always be reviewed in the actual component context. A short manual test with a keyboard and a screen reader will catch problems that automated scanners cannot.

Sources

Run a free WCAG 2.1 AA scan on your site

ADA CodeFix scans your pages, identifies likely WCAG failures, and generates developer-reviewable code fixes for ARIA labels, form labels, focus styles, alt text, color contrast, and more.

Scan My Site Free