ARIA Labels: When Native HTML Beats the Attribute
An ARIA label names a control with no visible text. When to use aria-label, when native HTML wins, and the misuse that hides the words on your button.

An ARIA label names a control with no visible text. When to use aria-label, when native HTML wins, and the misuse that hides the words on your button.

An aria-label is a string that becomes an element's accessible name when no usable text is on screen. MDN documents it for icon-only controls. The W3C APG wants that name short, typically 1-3 words, announced with the role ("Close, button").
aria-label replaces other name sources. It does not add a second label. Home pages in the WebAIM Million averaged 31.4 name and description ARIA attributes in 2026, on top of 133 ARIA attributes per page.
If you ship icon-only Close, SVG-inside-<button>, or a hamburger, aria-label is already in the file. Voice-control users say the words they can see; when the accessible name disagrees with those pixels, the click misses.
aria-label is the attribute this page covers. WAI-ARIA (Accessible Rich Internet Applications) is the spec. Web accessibility policy lives elsewhere.
aria-label replaces the name the browser would have computed from visible text, <label>, or alt.aria-labelledby pointing at on-page text, then visually hidden DOM text, then aria-label last.<label for>.<div>, skipping translation, and testing only in VoiceOver.An ARIA label (aria-label) defines a string that can name an element, as long as the element's role allows naming. Screen readers announce that name with the role. Voice-recognition users must say that name to target the control.

The name is not the role and not the state. Role comes from role or the native element's implicit role. State comes from aria-pressed, aria-expanded, and similar.
An accessible description is extra: a hint, error, or format note. aria-describedby does not create a name.
WAI-ARIA 1.2 is the current Recommendation; ARIA 1.3 is a Working Draft (4 June 2026). ARIA in HTML (11 August 2026) is the HTML-author table for which roles may be named.
Pages with ARIA in the 2026 WebAIM Million averaged 59.1 errors; pages without averaged 42. WebAIM's caveat: that gap is correlation, not proof ARIA caused the errors, because those pages were also more complex.
Empty buttons still showed up on 30.6% of home pages. That is the designer-facing failure: chrome with no name.

Browsers compute one accessible name. Authors choose how to supply it. Those are two different orders.
Mixing them up is how teams type aria-label first and then wonder why visible copy disappeared.
AccName 1.2 (Working Draft, 30 April 2026) walks this order. MDN and web.dev match it:
aria-labelledby (referenced nodes, concatenated in listed order)aria-label (flat string)<label for>, alt, inner text)title (last-resort fallback)Description is a separate table: aria-describedby, then aria-description, then host features.
MDN's labelledby demo makes the precedence concrete. A button whose visible text is "Red", with aria-label="Blue" and aria-labelledby pointing at "Yellow", is named Yellow.
Type names in the opposite order from AccName (Adrian Roselli's list):
<button> text, <label for>, alt)aria-labelledby pointing at existing visible textaria-label lastPriority | Browser computes | You should type |
|---|---|---|
1 |
| Native HTML |
2 |
|
|
3 | Native / contents | Hidden DOM text |
4 |
|
|
AccName is what the engine does after you ship markup. Authoring priority is what you type so translation, voice control, and copy edits stay attached to pixels people can see.
Deque on WCAG 2.5.3 is the one-line version: adding aria-label does not add information. It replaces the other information.
aria-label gives the element its label (a string you author). An element with aria-labelledby is labelled by something else (an id reference). Léonie Watson put that pair in one sentence: both attributes "do the same thing but in different ways."
Attribute | Becomes the name? | Where the text lives | Use when |
|---|---|---|---|
Native | Yes (default) | On screen | Forms, text buttons, images |
| Yes, highest precedence | Usually visible | Visible text already exists |
| Yes, replaces others | In the attribute | No usable on-page text |
| No | Visible or SR-only | Hints, errors, format |
| Almost never useful | Tooltip | Do not use as the name |
aria-labelledby can concatenate several nodes (ARIA16). A missing id is a silent failure: the name becomes empty.
aria-describedby is announced after the name, or on request. It never substitutes for a missing name.
For most buttons the name is the text inside (MDN's button role, updated August 2026). Extra aria-label overrides it.
Sara Soueidan (@SaraSoueidan) (May 2019) made the designer point early: aria-label is the popular way to name icon buttons. It is not the only way. Visible text, visually hidden text, and aria-labelledby all produce a name.
Use it when text that could label the element is not visible. If visible text already labels it, use that instead (MDN).
Case | Why it is legitimate |
|---|---|
Icon-only Close, menu, search | No visible text; the role allows naming |
Two | Distinguishes "Primary" from "Secondary" when no heading exists to reference (ARIA6) |
Widget that cannot take | Last-resort naming, e.g. some |
Input with no practical visible label | Last resort; visual users get nothing |
The APG adds a design note: if an interactive element has no visually persistent text label, put one on screen. Visible labels also help voice users, magnification, and translation.
Label the control, not the graphic. Put aria-label on the <button>, and aria-hidden="true" plus focusable="false" on a decorative SVG. Prefer SVG over icon fonts; private-use-area glyphs announce as junk.
<button aria-label="Close">×</button>ARIA14 is a sufficient technique for WCAG 4.1.2 when no visible label can be used. Without the name, many screen readers announce "Times, button" or the multiplication symbol. With it, they announce "Close, button."
Name the action, not the glyph. aria-label="arrow-up" tells nobody what the control does. aria-label="Sort by name, ascending" does.
Do not put the word "button" in the name. The role is already announced, so "Send button" becomes "send button, button."
Using ARIA is a Discontinued Draft (24 February 2026). Its First Rule is still quoted everywhere: if a native HTML element or attribute already has the semantics and behavior you need, use it instead of repurposing an element and adding ARIA.
The living citation is the APG Read Me First: "No ARIA is better than Bad ARIA." ARIA is CSS for assistive technologies. Bad ARIA misrepresents the visual UI.
aria-label is a cloak: AT users hear only the aria-label, not the link text.
Abbey Perini (14 April 2025) wrote the correction teams actually need: people hear "never use ARIA," then refuse the icon-button case.
HTML tutorials still rank for this query with a truncated default: if you cannot use a <label>, use aria-label. That is a last resort, not the default. Visible <label>, then aria-labelledby, then aria-label.
Don't | Do |
|---|---|
|
|
Styled input plus |
|
| Make the visible text specific |
| Delete the attribute |
| Hide it or focus it, never both |
A span with role="button" is not a button and will not inherit Space-to-activate. Native <button> already has the role, the name (its text), keyboard behavior, and focus.
Eric Bailey's line: "aria-label is a code smell." The smell is using it where visible text, a <label>, or aria-labelledby already works.
If the control already has visible text, extra aria-label overwrites it. Copy drift then fails WCAG 2.5.3 Label in Name (Level A) and misses voice-control users.
Accede Web: a button that says "Confirm my order" with aria-label="Validate my order" is incorrect. F96 is the failure. G208 is the fix: the visible label is part of the name, best at the start.
<!-- Wrong: the accessible name is no longer the visible text -->
<button aria-label="Validate my order">Confirm my order</button>
<!-- Right: visible text is the name -->
<button>Confirm my order</button>Mergify (22 June 2026) reviewed a Claude-agent PR that renamed a button to "See scheduled freeze reference" and added a matching aria-label. That duplicate does nothing until copy drifts. Their warning case is visible text changing while aria-label="Learn more" stays.
Do not rescue "click here" by hiding a better name in aria-label. Rewrite the visible link text.
<div> and <span> Split Across Assistive TechDefault role is generic. ARIA in HTML says naming-prohibited roles MUST NOT take aria-label or aria-labelledby. ARIA 1.2 prohibited roles include caption, code, generic, paragraph, presentation, and strong.
Manuel Matuzović (May 2026) tested <div aria-label="News">Content</div> across eight assistive-technology combinations. VoiceOver on macOS Safari announced "News, group." JAWS 2026 and NVDA 2026.1.1 announced "Content" and ignored the label.
TalkBack in Chrome said "News"; TalkBack in Firefox said "Content." Testers who only use VoiceOver ship a "fix" JAWS and NVDA users never hear.
Support is split. Do not treat VoiceOver as the matrix.
Ben Myers bans the same pattern on static text. Naming a heading or generic wrapper does not give you a free screen-reader-only heading.
On r/css the failure mode is authors who think they labeled something:
"aria-label only reliably exposes on elements that already have a semantic role (button, link, input, landmarks). Put it on a plain div or span and many screen readers ignore it, so you think you added a label and actually shipped nothing." (u/sagarpatel1244 in r/css, May 2026)
<!-- Wrong: generic element, naming prohibited -->
<div aria-label="News">Content</div>
<!-- Right: a real heading, or a named landmark if you need a region -->
<section aria-labelledby="news-heading">
<h2 id="news-heading">News</h2>
<p>Content</p>
</section>Visible DOM text goes through the page's translation. aria-label stays in the attribute.
Adrian Roselli (updated 4 March 2023) showed Chrome and Edge can translate visible text while leaving aria-label in the original language. Natalie MacLees described the same bug: a control shows "Buscar" and announces "Search."
On r/accessibility, u/k4rp_nl (Dec 2023) put the same tradeoffs in one thread: aria-label does not translate, and aria-labelledby overwrites aria-label. Pick neither when possible, because native HTML is more robust for the user and less complex for the writer.
If you must use aria-label, put it in the same localization pipeline as visible strings. Or point aria-labelledby at text that already lives in the DOM.
WCAG 2.5.3 requires the visible text to be contained in the accessible name. Ashlee M Boyer documented a stricter practical failure: Apple Voice Control (as of July 2024) often wants the entire name spoken.
Visible "OK" plus aria-label="Confirm selection" means saying "OK" misses. WCAG 2.5.3 is containment; exact match is what speech users can actually operate.
Invisible names also fail people who cannot see the attribute. Boyer noted that a long, complicated aria-label is not on screen, so speech-recognition users cannot know what to say:
Not only are links now inaccessible to screen reader and keyboard users, they’re also inaccessible to speech recognition users. The aria-label can be long and complicated, and isn’t visible. This means speech rec. users can’t know what to say to have their device open a link.
A long marketing aria-label on a short visual label is a speech-recognition dead end. Stefan Judis logged the same failure from the other direction: people try to speak the visual label.
Firefox's Accessibility Inspector is the designer debug move. Open the Name property: null means unnamed, and a Name that disagrees with visible text means aria-label is overriding content.
Assistive technology may announce path data or "graphic, Home." Name the <button>. Hide the SVG.
<button type="button" aria-label="Close">
<svg aria-hidden="true" focusable="false" width="16" height="16">
<!-- decorative paths -->
</svg>
</button>Never combine aria-hidden="true" with a focusable control. Hide it or leave it in the tab order.
Do not use aria-label to dump extra screen-reader-only information. WebAIM flags that as an inconsistent experience, because it also overrides other name sources such as link text.

A wireframe is a skeletal screen layout for UI. Get lo-fi vs hi-fi, a skip-to-AI decision table, and how to sketch structure before you polish pixels.

A complete guide to writing a web design proposal that wins clients. Covers the 8-section structure, real $4k–$15k pricing breakdowns, the two-option strategy,

Master self-serve SaaS UX: Build seamless journeys from landing page demos to smart onboarding and advanced learning paths. Reduce friction and boost activation