Skip to content

IDs need to be unique

  • Rule: axe/duplicate-id
  • Checks: id attribute value must be unique
  • WCAG: 4.1.1
  • Fix class: mechanical: A fix needs no authored text or visual decision.
  • People who use a keyboard or a switch device instead of a mouse.
  • People who use a screen reader or a braille display, most of them blind.

A component that renders more than once uses a fixed id

Section titled “A component that renders more than once uses a fixed id”

Generate an id for each instance, such as a prefix plus the item’s key, and use the same value wherever the page refers to it. No label or ARIA attribute points at this id, but a same-page link or a script may, and those find only the first element with it.

The same markup is on the page twice, such as a menu for small screens and another for large ones

Section titled “The same markup is on the page twice, such as a menu for small screens and another for large ones”

Render one copy and restyle it with CSS, or add a distinct suffix to each copy’s ids. A copy hidden with CSS still counts.

Use a class or a data- attribute, which may repeat. Keep ids for elements that a link, label or ARIA attribute points at.

Renaming one duplicate without updating what refers to it

Section titled “Renaming one duplicate without updating what refers to it”

Links, styles and scripts that used the old id then point at nothing, or at the wrong element.

Generating a new random id on every render

Section titled “Generating a new random id on every render”

The ids are unique, but they change between visits, so links people bookmark or share to that part of the page stop working.

The part of the fix that differs in React, in its syntax. The rest of the guidance holds.

A component that renders more than once hard-codes an id

Section titled “A component that renders more than once hard-codes an id”

For an id that only your own markup refers to, build it from useId. For one people link to, such as a same-page anchor, build it from the item’s unique key or slug instead, since useId values follow the component tree and change when it does.

function FaqItem({ slug, question, answer }) {
return (
<div id={`faq-${slug}`}>
<h2>{question}</h2>
<p>{answer}</p>
</div>
);
}

Generating the id with Math.random() or a counter

Section titled “Generating the id with Math.random() or a counter”

The value differs between the server and the client, which causes a hydration mismatch, and it changes on every render, which breaks links and scripts that kept an earlier value.

axe-core’s documentation of the rule

CORA’s fix guidance adapts content from accessibility-agents, under the MIT License: see its notice.