Warninga11y.duplicate-id

The same id is used more than once

Why it matters

An id is meant to name one element. When two share it, anything that points at it finds only the first: a <label for="email"> labels the first field called email and leaves the second with none, aria-labelledby reads out the wrong heading, and a link to #contact lands on whichever comes first. It happens when a form or a widget is put on a page twice (the newsletter box in the sidebar and the footer).

That is when it is a warning here: a label or an ARIA attribute points at the id that is shared. A shared id that nothing points at harms nobody yet, and is a notice. WCAG used to fail every duplicate under 4.1.1 Parsing; that criterion was withdrawn in WCAG 2.2 because browsers now cope, and what is left is the real harm, which falls under the criteria below.

Sources: WCAG 2.2, 1.3.1 Info and Relationships and 4.1.2 Name, Role, Value; why 4.1.1 Parsing was removed.

How to fix it

Give each copy an id of its own, and point its label at it:

<label for="footer-email">Email</label>
<input id="footer-email" type="email" name="email">

If a component is rendered more than once, build its ids from something unique to each copy.

Examples

These are the rule's own test pages, and what it says about each. They are run on every change to the rule book.

<aside>
<label for="email">Email</label>
<input id="email" type="email">
</aside>
<footer>
<label for="email">Email</label>
<input id="email" type="email">
</footer>

Warning1 id that a label or ARIA attribute points at is used more than once, so only the first element gets the name: "email" (2 times).

fail-label-target
<div id="promo">Free delivery</div>
<div id="promo">Order by Thursday</div>

Notice1 id is used more than once: "promo" (2 times). Nothing points at it yet, so nothing is broken, but the next label or in-page link will find only the first.

fail-unreferenced
<aside>
<label for="side-email">Email</label>
<input id="side-email" type="email">
</aside>
<footer>
<label for="footer-email">Email</label>
<input id="footer-email" type="email">
</footer>

PassedNo id is used twice.

pass-unique