# Elements must have their visible text as part of their accessible name

> Canonical HTML version: https://rocketvalidator.com/accessibility-validation/axe/4.14/label-content-name-mismatch
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

When an interactive element displays visible text, like a button that says "Submit", users expect that text to be the element's name. Developers sometimes use `aria-label` or `aria-labelledby` to set an accessible name that differs from the visible text. Sighted users then see one name while assistive technologies announce another.

This is a serious accessibility problem, and speech input users get the worst of it. They operate a page by speaking the names of the controls they see. If someone sees a link labeled "Next Page" and says "click Next Page", but the accessible name is "OK", the command fails. The user has no way to find out the programmatic name, so for them the control might as well not exist.

Screen reader users and people with cognitive disabilities are affected too. When a screen reader announces a name that doesn't match the visible label, users can't be sure they're on the right element. People who rely on a consistent, predictable interface have one more inconsistency to work around.

This rule checks **Success Criterion 2.5.3: Label in Name** (Level A), which is part of both WCAG 2.1 and WCAG 2.2. When a user interface component has a visible text label, its accessible name must contain that text. That way people can operate the component with the words they see, whatever input method they use.

Starting with axe-core 4.14, this rule runs by default. Earlier versions shipped it as an experimental rule that tools had to turn on, and Rocket Validator already did. What changed in 4.14 is how the rule compares the text, described below.

## Which elements are checked

The rule applies to elements that meet all three conditions:

1. It has a widget role that supports name from content: `button`, `checkbox`, `gridcell`, `link`, `menuitem`, `menuitemcheckbox`, `menuitemradio`, `option`, `radio`, `searchbox`, `switch`, `tab`, or `treeitem`.
2. It has visible text content.
3. It has an `aria-label` or `aria-labelledby` attribute that overrides the default accessible name.

## How the visible text is compared

Axe compares the visible text with the accessible name word by word, ignoring case. Before comparing, it cleans up both strings:

- Anything inside parentheses is removed, including nested parentheses. A visible "Download report (PDF, 2 MB)" is compared as "download report".
- Emoji are removed, and other punctuation and symbols separate words, so "sign-in" becomes the two words "sign" and "in".
- Full-width and other compatibility characters are normalized to their plain forms.
- For scripts written without spaces between words, such as Chinese, Japanese, Korean or Thai, the browser's word segmenter splits the text into words.
- Icon font ligatures, such as the `arrow_forward` text that Material Icons turns into an arrow, are not counted as visible text.

The rule passes when all the words of the visible text appear in the accessible name, in the same order, with no other words between them. The accessible name can have extra words before or after.

Axe matches whole words. Before 4.14, it only checked whether the visible text appeared somewhere inside the accessible name, so a button showing "Subscribe" with `aria-label="Unsubscribe"` passed. It fails now, because "subscribe" and "unsubscribe" are different words.

### When axe asks for a manual review

Sometimes axe can't decide, so it reports the element as needing review instead of failing it. That happens in two situations.

The first is text a person can't read as a label. If the visible text or the accessible name is a single non-digit character (like "×" or "›"), contains only punctuation or symbols, or is a symbolic string such as "aA" or "abc", axe leaves the call to you.

The second is text that may be a value. On `checkbox`, `radio`, `switch`, `menuitemcheckbox` and `menuitemradio` elements, the visible text is sometimes the current state, like "On" or "Off", and not the label. If that text isn't in the accessible name, axe asks for a review.

## How to Fix

1. Make the accessible name include all of the visible text. If the element shows "Next Page", the `aria-label` must contain the words "Next Page", in that order. Part of the text isn't enough, and neither is a different wording.
2. Start the accessible name with the visible text. It isn't strictly required, but speech input users may only say the beginning of a label, so it's the safer choice.
3. Consider removing the `aria-label` entirely. If the visible text works as an accessible name on its own, you don't need an override, and letting the element take its name from its content is often the simplest fix.
4. When a toggle comes back for review, look at what its visible text is. A value like "On" doesn't need to be part of the name, so the review can be closed. If the text is the control's label, add it to the accessible name.

## Examples

### Failing: Accessible name doesn't match visible text

The visible text says "Next" but the accessible name is "OK":

```html
<div role="link" aria-label="OK">Next</div>
```

### Failing: Accessible name only contains part of the visible text

The visible text is "The full label" but the accessible name is "the full", which leaves out "label":

```html
<button aria-label="the full">The full label</button>
```

### Failing: The words are in a different order

Both strings contain the same words, but "Next Page" doesn't appear in that order in the accessible name:

```html
<button aria-label="Page next">Next Page</button>
```

### Failing: The visible word is only part of a longer word

"Subscribe" appears inside "Unsubscribe", but not as a whole word. This example passed before axe-core 4.14:

```html
<button aria-label="Unsubscribe">Subscribe</button>
```

### Passing: Accessible name matches visible text

Case differences and surrounding whitespace are ignored:

```html
<div role="link" aria-label="Next Page">next page</div>
```

### Passing: Accessible name contains the full visible text

The visible text "Next Page" appears, in order, within the accessible name:

```html
<button aria-label="Next Page in the list">Next Page</button>
```

### Passing: Punctuation and parenthesized text are ignored

The hyphen in "Sign-in" separates words, and the "(PDF, 2 MB)" note is removed before comparing:

```html
<button aria-label="Sign in to your account">Sign-in</button>
<a href="/annual-report.pdf" aria-label="Download annual report">Download annual report (PDF, 2 MB)</a>
```

### Passing: No aria-label override needed

When the visible text is already a good accessible name, leave out the `aria-label`:

```html
<button>Next Page</button>
```

### Passing: aria-labelledby references text that includes the visible content

```html
<span id="btn-label">Search the full catalog</span>
<button aria-labelledby="btn-label">Search</button>
```

The visible text "Search" is part of the accessible name "Search the full catalog", so the rule passes. The accessible name also starts with the visible label, which is ideal for speech input users.

### Needs review: The visible text is a single symbol

Axe can't judge whether "×" is meant as a label:

```html
<button aria-label="Close dialog">×</button>
```

### Needs review: The visible text is the switch's state

"On" isn't part of the accessible name "Dark mode", but it describes the switch's value, not its label:

```html
<div role="switch" tabindex="0" aria-checked="true" aria-label="Dark mode">On</div>
```
