# ARIA tab elements must have an accessible name

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

A tab is one of the interactive controls in the ARIA tabs pattern, where a `tablist` holds several `tab` elements and each tab reveals its matching `tabpanel`. The accessible name is what a screen reader reads out when focus lands on the tab, so it has to describe the section that the tab opens, such as "Profile", "Security", or "Notifications". When the name is missing, assistive technology falls back to announcing only the role, so the user hears "tab" with nothing to tell one tab from the next.

This shows up most often with icon-only tabs, where the tab holds a single icon and no text, and with tabs built from empty `div` or `span` elements styled entirely through CSS. In both cases there is visible meaning on screen, through an icon or a background image, but nothing that assistive technology can read. Keyboard and voice-control users are affected too, since voice commands often target a control by its name.

This rule maps to WCAG Success Criterion 4.1.2 Name, Role, Value (Level A). That criterion requires every user interface component to expose its name, its role, and its current state to assistive technology. A tab already carries its role through `role="tab"` and its state through `aria-selected`, but without a name the component is only partly exposed, so the criterion is not met. Level A is the minimum conformance level, and the same criterion applies in WCAG 2.0, 2.1, and 2.2.

## How to Fix

Give every element with `role="tab"` an accessible name using one of these techniques, listed from most to least preferred:

- Put the label text directly inside the tab, so the name is visible to everyone.
- Use `aria-labelledby` to reference the `id` of an element that already holds the label text.
- Use `aria-label` to set the name directly, which suits icon-only tabs that have no visible text.
- Use the `title` attribute as a fallback when none of the above fit.

Whichever technique you pick, make the name describe where the tab leads and keep it unique within the tablist, so each tab is easy to tell apart.

## Examples

### Failing: Icon-only tab with no name

The tab shows an icon but exposes no text, so a screen reader announces only "tab".

```html
<div role="tablist">
  <button role="tab" aria-selected="true">
    <svg aria-hidden="true" focusable="false"><!-- gear icon --></svg>
  </button>
</div>
```

### Failing: Empty `aria-label`

An `aria-label` with no value leaves the tab without a name.

```html
<button role="tab" aria-selected="true" aria-label="">
  <svg aria-hidden="true" focusable="false"><!-- bell icon --></svg>
</button>
```

### Failing: `aria-labelledby` pointing nowhere

If the referenced `id` does not exist, or the element it points to is empty, the tab still has no name.

```html
<button role="tab" aria-selected="true" aria-labelledby="missing-label">
</button>
```

### Passing: Visible text inside the tab

```html
<div role="tablist">
  <button role="tab" aria-selected="true">Profile</button>
  <button role="tab" aria-selected="false">Security</button>
</div>
```

A screen reader announces something like "Profile, tab, selected".

### Passing: `aria-label` on an icon-only tab

```html
<button role="tab" aria-selected="true" aria-label="Notifications">
  <svg aria-hidden="true" focusable="false"><!-- bell icon --></svg>
</button>
```

The icon stays decorative with `aria-hidden="true"`, while `aria-label` supplies the name.

### Passing: `aria-labelledby` referencing visible text

```html
<span id="billing-label">Billing</span>
<button role="tab" aria-selected="false" aria-labelledby="billing-label"></button>
```

This keeps the visible label and the accessible name in sync, since both come from the same text.
