About This Accessibility Rule
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-labelledbyoraria-describedbymay point to the wrong content, giving users incorrect or missing context. -
Interactive components that depend on
aria-owns,aria-controls, oraria-activedescendantmay 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
-
Identify all duplicate
idvalues that are referenced by ARIA attributes (aria-labelledby,aria-describedby,aria-controls,aria-owns,aria-activedescendant, etc.) or by a<label>element’sforattribute. -
Rename the duplicate
idvalues so that each one is unique within the document. -
Update any references to those
idvalues in ARIA attributes orforattributes to match the new unique values. - 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.
<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
<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
<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
<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
<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
<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">
Help us improve our guides
Detect accessibility issues automatically
Rocket Validator scans thousands of pages with Axe Core and the W3C Validator, finding accessibility issues across your entire site.