# IDs used in ARIA and labels must be unique

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

## Why This Is an Accessibility Problem

In HTML, the `id` attribute is designed to be a unique identifier for a single element in the document. When two or more elements share the same `id`, the browser has no reliable way to determine which element is being referenced. This becomes a critical accessibility barrier when that `id` is used to create relationships between elements — such as linking a `<label>` to a form input, or connecting a description to a widget via `aria-describedby`.

Assistive technologies like screen readers rely on these `id`-based relationships to communicate information to users. When duplicates exist, the screen reader will typically resolve the reference to the **first** element in the DOM with that `id`, which may not be the intended target. This means:

- A **blind** or **deafblind** user may hear the wrong label for a form field, or no label at all.
- An ARIA relationship like `aria-labelledby` or `aria-describedby` may point to the wrong content, giving users incorrect or missing context.
- Interactive components that depend on `aria-owns`, `aria-controls`, or `aria-activedescendant` may break entirely.

This rule relates to **WCAG Success Criterion 4.1.2: Name, Role, Value** (Level A), which requires that all user interface components have accessible names and roles that can be programmatically determined. Duplicate `id` values used in ARIA or label associations directly undermine this requirement by creating ambiguous or broken programmatic relationships.

## How to Fix It

1. **Identify all duplicate `id` values** that are referenced by ARIA attributes (`aria-labelledby`, `aria-describedby`, `aria-controls`, `aria-owns`, `aria-activedescendant`, etc.) or by a `<label>` element's `for` attribute.
2. **Rename the duplicate `id` values** so that each one is unique within the document.
3. **Update any references** to those `id` values in ARIA attributes or `for` attributes to match the new unique values.
4. **Verify** that each relationship still works correctly by testing with a screen reader or the axe accessibility checker.

## Examples

### Incorrect: Duplicate `id` on elements referenced by `for`

In this example, two inputs share the same `id` of `"email"`. The second `<label>` intends to reference the second input, but both `for` attributes resolve to the first input.

```html
<label for="email">Personal Email</label>
<input type="email" id="email">

<label for="email">Work Email</label>
<input type="email" id="email">
```

A screen reader user tabbing to the second input would hear no label or the wrong label, making it impossible to know what information to enter.

### Correct: Unique `id` values for each input

```html
<label for="personal-email">Personal Email</label>
<input type="email" id="personal-email">

<label for="work-email">Work Email</label>
<input type="email" id="work-email">
```

### Incorrect: Duplicate `id` referenced by `aria-labelledby`

```html
<span id="section-title">Shipping Address</span>
<div role="group" aria-labelledby="section-title">
  <!-- shipping fields -->
</div>

<span id="section-title">Billing Address</span>
<div role="group" aria-labelledby="section-title">
  <!-- billing fields -->
</div>
```

Both groups would be announced as "Shipping Address" because the browser resolves both `aria-labelledby` references to the first `<span>` with `id="section-title"`.

### Correct: Unique `id` values for each referenced element

```html
<span id="shipping-title">Shipping Address</span>
<div role="group" aria-labelledby="shipping-title">
  <!-- shipping fields -->
</div>

<span id="billing-title">Billing Address</span>
<div role="group" aria-labelledby="billing-title">
  <!-- billing fields -->
</div>
```

### Incorrect: Duplicate `id` used in `aria-describedby`

```html
<p id="hint">Must be at least 8 characters.</p>
<label for="password">Password</label>
<input type="password" id="password" aria-describedby="hint">

<p id="hint">Re-enter your password to confirm.</p>
<label for="confirm-password">Confirm Password</label>
<input type="password" id="confirm-password" aria-describedby="hint">
```

### Correct: Unique `id` values for each description

```html
<p id="password-hint">Must be at least 8 characters.</p>
<label for="password">Password</label>
<input type="password" id="password" aria-describedby="password-hint">

<p id="confirm-hint">Re-enter your password to confirm.</p>
<label for="confirm-password">Confirm Password</label>
<input type="password" id="confirm-password" aria-describedby="confirm-hint">
```
