All WCAG rules
WCAG 4.1.1Level ASeriousStructure

How to fix: Duplicate element IDs

Every id attribute on a page must be unique: if the same id value appears on more than one element, rename the duplicates so each id is used only once.

What it is

An id is meant to be a unique handle for a single element. The HTML specification requires id values to be unique within a document, and a great deal of accessibility plumbing depends on that guarantee. WCAG Success Criterion 4.1.1 Parsing (in WCAG 2.1) treats duplicate IDs as a markup defect, because when two elements share an id, anything that points to that id becomes ambiguous: the browser and assistive technology can only resolve it to one element, usually the first.

Duplicates creep in easily. A reusable component (a card, a form field, a modal) gets rendered several times on the same page, each copy carrying the same hard-coded id. A template fragment is pasted twice. Two developers independently pick id="title". Visually nothing looks wrong, which is exactly why the problem goes unnoticed until something that relies on the id silently misbehaves.

The consequences are concrete. A <label for="x"> associates with only the first element that has id="x", so the second copy's field is effectively unlabeled. ARIA references like aria-labelledby, aria-describedby, and aria-controls resolve to the first match, so a control can announce the wrong name or description. In-page anchors (href="#x") and scripts that call getElementById jump to or operate on the wrong element. The fix is simply to make each id unique.

Who it affects & why it matters

Screen reader users are affected whenever a duplicated id sits behind a label or an ARIA relationship. If a field's <label for> or aria-labelledby resolves to the wrong (first) element, the user hears the wrong name or no name at all, which is especially damaging on forms where guessing the wrong field means a failed submission.

Keyboard and all users are affected when duplicated IDs break in-page skip links and anchor navigation, sending focus to the wrong spot, and scripts that target an element by id can act on the wrong one, producing erratic behavior that is hard to trace. Because the page looks fine, these failures are easy to ship and hard to debug, hurting reliability for everyone.

Duplicate IDs fall under SC 4.1.1, a Level A criterion, the most basic conformance tier. They are trivial for automated tools to detect, which is exactly why they show up in audits and in the demand letters plaintiff firms send. WCAG 2.1 Level AA is the de-facto benchmark U.S. courts apply to ADA Title III claims, and it includes every Level A criterion, so a documented Level A markup failure is an obvious item to clear.

Web accessibility lawsuits keep climbing year over year and most often target businesses under $25 million in revenue, and duplicate IDs are doubly costly because they are both a flagged violation and a real source of broken labels and navigation. Renaming a handful of ids is a quick, low-risk fix that removes an easy audit finding and restores the label, ARIA, and anchor wiring that depends on uniqueness.

How to fix it

  1. Collect every element with an id attribute and look for any id value that appears more than once.
  2. For each duplicated id, decide which element keeps the original value and rename the others to something unique and descriptive.
  3. Update everything that points at the renamed ids: matching label for attributes, aria-labelledby / aria-describedby / aria-controls references, href="#id" anchors, and any getElementById or querySelector calls.
  4. For reusable components that render multiple times, generate ids dynamically (for example by appending an index or a unique key) instead of hard-coding them.
  5. Re-scan to confirm every id on the page is now unique.
Before
<label for="email">Work email</label>
<input id="email" type="email">

<label for="email">Personal email</label>
<input id="email" type="email">
After
<label for="work-email">Work email</label>
<input id="work-email" type="email">

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

How AccessKnight detects this

AccessKnight selects every element that has an id attribute and tallies how many times each id value occurs. Any id value that appears more than once is flagged, and the finding reports the duplicated value and how many times it was used, with the fix to make that id unique. Each distinct duplicated id produces its own finding. Elements with a unique id, or with no id at all, are not reported.

Frequently asked questions

Is a duplicate ID a Level A or AA issue?

It falls under WCAG 2.1 Success Criterion 4.1.1 Parsing, which is Level A, the minimum conformance tier. AccessKnight scores it as a serious-severity violation because duplicate IDs silently break label associations, ARIA references, and in-page anchors that real users depend on.

Why do duplicate IDs break accessibility if the page still renders?

Because the wiring that points at an id can only resolve to one element. A <label for="x"> attaches to the first id="x", leaving any later copy unlabeled; aria-labelledby and aria-describedby resolve to the first match, so a control can announce the wrong name; and anchor links and scripts target the wrong element. The page looks fine but behaves incorrectly for assistive technology and navigation.

How do I keep IDs unique in a reusable component?

Generate the id at render time instead of hard-coding it. Append the row index, the record's key, or a generated unique value so each instance gets its own id, and build the matching label for and ARIA references from the same generated value. That keeps every copy's wiring intact even when the component appears many times on one page.

Are duplicate class names a problem too?

No. Classes are designed to be shared across many elements, so reusing a class is correct and expected. This rule is specifically about the id attribute, which must be unique within a document. Only duplicate id values are flagged here.

Is this issue on your site?

AccessKnight scans any page against all 30 WCAG 2.1 rules — including this one — and shows every instance with a fix. Free, no credit card.

Scan my site free →

More WCAG fixes