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:
- The element has no visible text
- The visual label is an icon
- A short accessible name is needed
- The element is an interactive control
- There is no better visible text to reference
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:
- Visible text often provides the name.
aria-labelledbycan name an element using referenced visible text.aria-labelcan provide or override a name.- Native labels name form controls.
- Image alt text can name linked images or image buttons.
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:
- Icon buttons without accessible names
- Empty or vague
aria-labelvalues aria-labelthat conflicts with visible text- Broken
aria-labelledbyreferences - Broken
aria-describedbyreferences - ARIA used where native HTML would be better
- Form fields missing visible labels
- Regions with duplicate or unclear labels
- Custom controls with incomplete name, role, or state
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.
- Is ARIA necessary, or would native HTML be better?
- Does every interactive control have a clear accessible name?
- Does the accessible name match or support visible text?
- Are icon-only buttons labeled?
- Are
aria-labelledbyreferences valid? - Are
aria-describedbyreferences valid? - Is help text used as a description, not as a label replacement?
- Are form fields visibly labeled where possible?
- Are region labels unique when multiple regions exist?
- Are ARIA states updated when the UI changes?
- Has the component been tested by keyboard?
- 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
- W3C WCAG Understanding 4.1.2 Name, Role, Value (opens in new tab)
- W3C WAI-ARIA Authoring Practices Guide (opens in new tab)
- W3C ARIA in HTML (opens in new tab)
- W3C WAI ARIA Overview (opens in new tab)
- W3C WCAG Understanding 1.3.1 Info and Relationships (opens in new tab)
- W3C Web Accessibility Initiative (WAI) (opens in new tab)
- MDN ARIA labels (opens in new tab)
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 FreeRelated guides
Connect real labels to inputs, checkboxes, and radio groups for assistive tech.
Button accessibilityReplace clickable divs and icon-only buttons with named, keyboard-friendly controls.
Modal accessibilityGive dialogs accessible names, manage focus, and label close buttons.
WCAG 4.1.2 Name, Role, ValueHow accessible names and roles are exposed to assistive technology.