# axe-core label-content-name-mismatch error visible text missing from name - how to fix it

## TL;DR

Voice-control users activate buttons by speaking their visible text ('click Apply now'). When aria-label says something different ('Submit the application form'), the voice command fails and screen reader users hear a name that does not match what sighted users see. Make the accessible name start with the visible text: aria-label="Apply now, submits the application form". Re-run the focused axe rule to confirm.

This violation spikes after rebrands and marketing copy refreshes: the visible button text changes from 'Start free trial' to 'Get started', while the aria-label still says the old text. Add aria-labels to your copy-review checklist, or better, derive the aria-label from the same string as the visible text so they cannot drift apart.

The verbatim error looks like this:

```text
axe-core 4.x
Rule: label-content-name-mismatch (serious)
"Elements must have their visible text as part of their accessible name"

Element: [button aria-label="Submit the application form"]Apply now[/button]
  Visible text "Apply now" is not contained in the accessible name.
```

## Steps

1. Reproduce with the single rule:

```bash
npx @axe-core/cli https://example.com/careers --rules label-content-name-mismatch
```

Expected: controls whose visible text is missing from the accessible name are listed.

2. Compare the visible text with the accessible name (aria-label, aria-labelledby, or alt). The usual cause is a marketing rewrite of the visible text after the aria-label was written, or an aria-label that paraphrases instead of quoting.

3. Align them, keeping the visible text first:

```html
[button aria-label="Apply now, submits the application form"]Apply now[/button]
```

If the visible text alone is clear, drop the aria-label entirely and let the text be the name.

4. Re-run the focused scan. Expected output: 0 violations for label-content-name-mismatch.

5. Voice-test if possible: speak the visible text as a command and confirm the control activates.

6. Find drifted labels by comparing visible text against accessible names after any copy change. A quick audit approach: list all elements with aria-label and eyeball them against their rendered text.

7. Derive, do not duplicate. In components, build the accessible name from the visible text:

```js
// visible text and accessible name share one source
const label = 'Apply now';
[button aria-label={label + ', submits the application form'}]{label}[/button]
```

One source of truth prevents future drift.
## When to use

- Axe flags label-content-name-mismatch on buttons, links, or form controls.
- Voice-control users report that speaking the visible label does not activate the control.
- A redesign changed visible copy without updating aria-labels.

## When not to use

- The control has no accessible name at all (fix the *-name rule first).
- The mismatch is caused by translation (localize the aria-label with the same string pipeline as the visible text).
- The visible text is an icon with no text (that is button-name or svg-img-alt territory).

## Why it happens

WCAG 2.5.3 (Label in Name) requires the accessible name to contain the visible label text, specifically so speech-input users can operate controls by speaking what they see. A paraphrased aria-label breaks that contract silently: everything looks fine in a screen reader rotor, but voice commands fail. Keeping the visible text verbatim at the start of the name satisfies both audiences.

aria-label is invisible in the UI, so it rots. Visible copy gets reviewed, tested, and translated; aria-labels get written once and forgotten. The mismatch rule catches the rot, but only if it runs. Teams that run axe only on page templates miss component-level drift, which is why the rule should also run against the component library's rendered stories.

## Edge cases

- The match is case-insensitive and ignores extra whitespace, but keep it verbatim anyway for voice users.
- Hidden accessible-name suffixes ('Apply now, opens in a new tab') are fine as long as the visible text comes first.
- aria-labelledby pointing at the visible text element plus extra context passes; aria-label paraphrasing it does not.
- Icon fonts or ligature text that renders as an icon may not match the DOM text. Use real text or an [svg] with a title.
- Translations multiply the drift: the visible text gets translated, the aria-label does not. Route aria-labels through the same i18n pipeline.
- aria-labelledby referencing the visible text element is drift-proof by construction. Prefer it over aria-label when the text exists in the DOM.
- Truncated visible text (CSS ellipsis) still counts as the visible text. Keep the full text in the accessible name.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_IF-CmaAu0jrGuuAPtEVrSw
