ARIA labels are attributes that provide accessible names to elements when the visible content does not give screen readers enough information to identify them. Defined by the Accessible Rich Internet Applications specification from the W3C, the two most important attributes are aria-label and aria-labelledby. They are essential for icon-only buttons, custom widgets, complex navigation, and anywhere visible text is missing or ambiguous. Used correctly, ARIA labels make interfaces usable for screen reader users. Used incorrectly, they create silent failures that hurt the very users they were meant to help.
What ARIA Labels Actually Do
Screen readers announce interactive elements by computing an accessible name. For a button with visible text “Submit,” the accessible name is “Submit” — no ARIA needed. For an icon-only button like a search magnifying glass, there is no visible text, so the screen reader has nothing to announce. ARIA labels solve this by providing an explicit, programmatic name.
The browser exposes the accessible name through the accessibility tree, an alternative representation of the page that assistive technology consumes. Without an accessible name, an icon button is announced as “button” — useless. With an ARIA label, it becomes “Search, button” — clear.
The First Rule of ARIA
The W3C explicitly states: “No ARIA is better than bad ARIA.” If you can use a native HTML element with built-in semantics, do that. A native <button> with visible text needs no ARIA. A <label> attached to an <input> needs no ARIA. ARIA is for the cases where HTML alone cannot express what you need — primarily, where visible content is missing or where you are building a custom widget native HTML cannot create.
aria-label vs aria-labelledby
The two attributes solve the same problem differently. Choosing the right one matters.
aria-label
Takes a string as the value. The string becomes the accessible name, overriding any visible content.
<button aria-label="Close dialog">
<svg aria-hidden="true">...</svg>
</button>
Use when there is no visible text on screen that could serve as the label, or when the visible text is ambiguous and needs an explicit override.
aria-labelledby
Takes one or more element IDs. The text content of those elements becomes the accessible name.
<h2 id="section-title">Pricing Plans</h2>
<section aria-labelledby="section-title">
...
</section>
Use when the label already exists somewhere on the page as visible text. Referencing it keeps the visible and accessible names in sync automatically — change the visible text, and the screen reader announcement changes too.
When to Choose Which
- Visible text exists for the label → aria-labelledby.
- No visible text exists (icon button, decorative wrapper) → aria-label.
- Label needs to combine multiple visible elements → aria-labelledby with multiple IDs.
- Label exists in a different language or contains non-text content → aria-label.
Important precedence rule: aria-labelledby wins over aria-label, which wins over any visible content. Setting both is almost always a mistake.
Common ARIA Label Patterns
A handful of patterns cover most situations on a modern website.
Icon-Only Buttons
The single most common use case. Search icons, hamburger menus, close buttons, social share buttons.
<button aria-label="Open menu">
<svg aria-hidden="true">...</svg>
</button>
The SVG gets aria-hidden="true" so the screen reader does not try to announce the icon path. The button itself gets the label.
Form Fields Without Visible Labels
Sometimes design constraints hide the label. The placeholder is not a label — placeholders disappear when users start typing. Use aria-label or a visually-hidden label.
<input type="search" aria-label="Search products" placeholder="Search..." />
Better: keep a real <label> in the DOM and visually hide it with CSS so screen readers and developers both see it.
Landmark Regions
Multiple <nav>, <aside>, or <section> elements on the same page need labels to distinguish them.
<nav aria-label="Primary">...</nav>
<nav aria-label="Footer">...</nav>
Screen readers list landmarks; without unique labels, users hear “navigation” multiple times with no way to choose.
Dialog and Modal Titles
Dialogs should be labeled by their visible heading.
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
<h2 id="dialog-title">Confirm Deletion</h2>
...
</div>
Buttons That Repeat
A list of “Edit” and “Delete” buttons repeating for every row tells a screen reader user “Edit, Edit, Edit, Edit” with no context. Add specific labels.
<button aria-label="Edit user Jane Doe">Edit</button>
<button aria-label="Delete user Jane Doe">Delete</button>
aria-describedby — A Related Tool
Often confused with labelledby, aria-describedby is for supplementary descriptions, not the primary name. A password field can have a label (“Password”) plus a description (“Must contain 8+ characters with at least one number”).
<label for="pw">Password</label>
<input id="pw" type="password" aria-describedby="pw-hint" />
<p id="pw-hint">Must contain 8+ characters with at least one number.</p>
The screen reader announces “Password, edit text, must contain 8+ characters with at least one number” — name first, description second.
Common ARIA Label Mistakes
ARIA mistakes are among the most damaging accessibility issues because they silently break the experience for users who depend on assistive technology. Watch for these patterns.
Redundant Labels
Adding aria-label="Submit" to a button that already displays “Submit” as text is redundant. Worse, if the label and visible text differ, screen reader users hear something different from what they see. Only add ARIA labels when no visible text exists.
Labels That Mismatch Visible Text
The WCAG “Label in Name” success criterion requires that the accessible name include the visible text. A button labeled visually as “Submit Order” with aria-label="Place order" fails this criterion. Voice control users who say “click Submit Order” cannot operate the button because the accessible name is different.
Labels on Non-Interactive Elements
Putting aria-label on a <div> or <span> with no role does nothing useful. Screen readers may not announce non-interactive elements at all. ARIA labels belong on interactive elements (buttons, links, form fields) or landmarks (nav, main, section).
Hiding Icons Without aria-hidden
An SVG icon inside a labeled button without aria-hidden="true" may get announced — “icon graphic, button, Search.” Add aria-hidden="true" to decorative SVGs so the label alone is announced.
Overusing ARIA
Replacing native semantics with ARIA. <div role="button"> instead of <button>. <div role="link"> instead of <a>. The native elements come with keyboard handling, focus management, and platform conventions for free. ARIA-only re-creations almost always have subtle bugs.
aria-labelledby Pointing to Non-Existent IDs
If aria-labelledby="section-title" references an ID that does not exist on the page, the label is empty. Audit for this during testing.
Hidden Elements Used as Labels
An element referenced by aria-labelledby is read even if it has display: none or visibility: hidden. This can be intentional, but it can also surface text users were never supposed to see. Use aria-hidden="true" only when you specifically want to hide from assistive technology too.
Testing ARIA Labels
Automated tools catch some ARIA errors, but the only reliable test is to listen with a screen reader.
- Browser DevTools accessibility tree — Chrome and Firefox both show the computed accessible name for any element. Inspect every interactive component.
- axe DevTools — flags missing labels, label mismatches, and broken labelledby references.
- NVDA (Windows, free) — install and tab through your site. Listen to what each control announces.
- VoiceOver (macOS / iOS) — built into Apple platforms. Cmd+F5 to enable.
- TalkBack (Android) — for testing on mobile devices.
If the screen reader announcement matches what a sighted user perceives, ARIA is working. If it does not, fix it. Our website accessibility guide covers the broader testing process.
ARIA Patterns Beyond Labels
ARIA is broader than just labels. The full specification covers roles, states, properties, and live regions. The most important to know:
- role=”button”, role=”link”, etc. — use only when native HTML cannot deliver the semantics.
- aria-expanded — announces whether a disclosure (accordion, menu, dropdown) is open or closed.
- aria-current=”page” — marks the current navigation item.
- aria-live — announces dynamic content updates without taking focus.
- aria-controls — links a control to the element it controls.
- aria-selected, aria-checked — state for tabs, checkboxes, listbox options.
The W3C maintains the ARIA Authoring Practices Guide with detailed patterns for tabs, menus, comboboxes, modals, and other complex widgets. Reference it whenever you build a custom component.
ARIA Labels and Internationalization
ARIA label strings are user-facing content and must be translated alongside everything else on the site. If your site supports French, the close button’s aria-label should be “Fermer” on French pages, not “Close.” Hard-coded English ARIA strings in a translated site are a common oversight.
The Future of ARIA
ARIA 1.3 is in development with new roles for emerging UI patterns and improved support for math, annotations, and complex grid widgets. The broader direction is toward better native HTML elements — <dialog>, <details>, <search>, <selectmenu> — that reduce the need for ARIA at all. The first rule still holds: prefer native semantics where they exist; reach for ARIA when they do not.
FAQ
Can I use aria-label on any HTML element?
No. ARIA labels work on interactive elements (buttons, links, form fields) and on elements with explicit roles (landmarks, dialogs, custom widgets). Adding aria-label to a plain div or span typically does nothing because the element has no accessible role for the label to attach to. If you find yourself wanting to label a div, the right fix is usually to use a semantic element like button, nav, or section instead.
Should I add aria-label to my form fields?
Use a real <label> element first. Labels are visible, clickable, and have built-in semantic meaning. Only reach for aria-label when design constraints make a visible label impossible — and even then, a visually-hidden label is usually a better choice because sighted developers and editors can see it in the DOM.
How do I test if my ARIA labels work correctly?
Use a screen reader. NVDA on Windows is free; VoiceOver is built into macOS and iOS; TalkBack into Android. Tab through your site and listen to what each control announces. If you can identify every interactive element by its announcement alone — without seeing the screen — the ARIA is working. Browser DevTools also show the computed accessible name for any element, which makes spot-checking fast.
Want a site built with accessible markup, proper ARIA, and zero overlay band-aids? See our pricing or get in touch.
