Level A

When aria-label overrides visible button text with a different string, voice-control commands targeting the visible label fail silently -- the accessibility tree no longer contains the word the user spoke

2.5.3 Label in Name

In Plain Language

2.5.3 Label in Name (Level A, new in WCAG 2.1) says that for user-interface components with labels that include text or images of text, the accessible name must contain the text that is presented visually[1]. The accessible name is the string computed by the browser's accessible-name algorithm from sources like aria-labelledby, aria-label, the associated <label>, the alt attribute, or the element's text content. If that computed string does not contain the visible label text, the control fails 2.5.3.

The failure is mechanical: voice-control software matches spoken phrases against the accessible names in the page's accessibility tree. When aria-label silently replaces the visible text with a different string, the match lookup fails and the control becomes unreachable by voice.

Why It Matters

  • Voice-control software (Dragon NaturallySpeaking, Windows Voice Access, macOS Voice Control, Android and iOS Voice Access) issues commands of the form "Click [visible label]". The software resolves the command by matching the spoken phrase against accessible names exposed by the platform accessibility API. When the accessible name does not contain the visible label text, the match fails and the command has no target -- the click lands nowhere, silently.
  • The accessible-name algorithm is deterministic: aria-labelledby beats aria-label, which beats the native label source (<label for>, alt, or text content). An aria-label added "to be helpful" does not append to the visible text -- it replaces it. A button reading <button aria-label="Send form">Submit</button> has the accessible name "Send form", and a voice-control user saying "Click Submit" issues a command that does not resolve.
  • Screen-reader users collaborating with sighted colleagues hit the same mismatch: the colleague says "click the Search button", the screen-reader user searches the reading order for "Search", and nothing matches because the control announces "Find items".
  • The failure is invisible in QA that only tests with a mouse -- the button looks right, clicks right, and passes any test that does not exercise voice input or screen-reader navigation by label.

Examples

Do: Accessible name matches the visible label

✔ Accessible name "Search" matches the visible label. Speech-input user says "Click Search" and it works.

<!-- Accessible name matches visible text -->
<button aria-label="Search">Search</button>

<!-- Better: let the text content be the accessible name -->
<button>Search</button>
Don't: aria-label replaces the visible text with a different string

✘ Visible label is "Search" but accessible name is "Find items". Speech user says "Click Search" -- nothing happens.

<!-- FAIL: aria-label overrides visible text with a different string -->
<button aria-label="Find items">Search</button>

<!-- Accessible name resolves to "Find items"; "Click Search" has no target -->
Do: Extra context, but the visible label text is preserved and comes first

✔ Accessible name starts with "Add to cart" and appends disambiguating context. Voice match on "Add to cart" still resolves.

<!-- Visible text is contained in, and starts, the accessible name -->
<button aria-label="Add to cart -- hiking boots, $79">
  Add to cart
</button>

<!-- Placing the visible label first is a 2.5.3 best practice -->
Don't: Input's <label> is overridden by a mismatched aria-label

✘ Visible <label> says "Email address" but aria-label overrides it to "Enter your corporate login ID." Voice command "Click Email address" fails.

How to Fix It

  1. Do not override the accessible name unless you need to. A <button> with text content and an <input> associated with a <label for> already compute an accessible name equal to the visible text. Adding aria-label replaces that, and every replacement is an opportunity to fail 2.5.3.
  2. When you do override, start the override with the visible text verbatim. A visible "Download" button becomes aria-label="Download -- Q4 financial report (PDF, 2.1 MB)". The visible string "Download" is contained in the accessible name, and placing it first means voice-control prefix matching still resolves[1].
  3. Audit every aria-label and aria-labelledby against the visible text. Grep the codebase for both attributes and, for each match, verify the rendered visible label is a substring of the computed accessible name. Icon buttons with adjacent text labels are the highest-yield place to look -- the icon-only aria-label gets reused after a redesign adds a visible caption, and nobody updates it.
  4. Prefer aria-labelledby pointing at the visible text node. When the accessible name must be built from multiple visible strings, aria-labelledby="id1 id2" concatenates the text content of the referenced elements -- the visible text is the accessible name by construction, and 2.5.3 cannot fail.
  5. Test with voice input, not just a mouse. Open macOS Voice Control or Windows Voice Access and walk every labeled control by saying "Click [visible label]". Any control that does not activate has a mismatch -- the accessible name does not contain the visible text.

References

  1. [1] W3C (2023). Understanding Success Criterion 2.5.3: Label in Name. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/label-in-name.html