Why Must Every HTML id Be Unique? Complete Guide (2026)

Saar Twito5 min read
Saar Twito
Saar TwitoFounder & SEO Engineer

Hi, I'm Saar - a software engineer, SEO specialist, and lecturer who loves building tools and teaching tech.

View author profile →

What Are Duplicate HTML IDs?

The HTML5 spec requires the id attribute to be unique per document — no two elements may share the same id. When duplicates appear, document.getElementById returns only the first match, <label for="..."> may bind to the wrong control, and ARIA references like aria-labelledby point to the wrong element. The result is silent breakage of JavaScript, accessibility, and in-page anchor links.

Key Facts (TL;DR)

  • Spec rule: HTML5 requires every id to be unique within the document.
  • JS impact: getElementById returns only the first match, ignoring all duplicates.
  • Accessibility: Duplicate IDs on form labels violate WCAG 1.3.1 (Info and Relationships).
  • ARIA impact: aria-labelledby and aria-describedby resolve only to the first matching id.
  • Audit name: Automated accessibility audits flag this as "[id] attributes on the page are unique".
  • Detection: Chrome DevTools Issues panel flags duplicates automatically.

What Each Duplicate ID Breaks (Reference Table)

Failure modeWhat breaksUser impact
document.getElementById(id)Returns only the first matchJS targeting the second element silently does nothing
<label for="id">Associates with the first matching controlClicking label focuses wrong field; screen reader announces wrong label (WCAG 1.3.1 fail)
aria-labelledby / aria-describedbyResolves to the first matching idScreen reader announces wrong description for buttons or controls
<a href="#id">Browser jumps to first occurrenceIn-page anchors and skip links land at the wrong section
CSS :target selectorMatches the first occurrence onlyStyling tied to URL fragments behaves unpredictably
Form submission with same name(separate from id, but often paired)Wrong field value submitted, autofill misbehaves

Common Causes of Duplicate IDs

  • Copy-pasted form components: A signup form duplicated in the footer keeps id="email" in both copies.
  • Server-rendered loops: Templating that renders id="item" for every row in a table.
  • Reusable UI components without id scoping: Modal, accordion, and tab components that hardcode an id.
  • Third-party widgets: Embedded chat, analytics, or ad widgets that use generic ids like id="close".
  • SPA route fragments: Components mounted twice during transitions before the previous instance unmounts.

Bad vs. Good Examples

A label binding to the wrong input is the most common duplicate-id bug. Here is the broken version followed by the fix.

<!-- BAD: two inputs share id="email" -->
<form>
  <label for="email">Contact email</label>
  <input id="email" name="contact_email" type="email">
</form>
<form>
  <label for="email">Newsletter email</label>
  <input id="email" name="newsletter_email" type="email">
</form>

<!-- GOOD: each id is unique -->
<form>
  <label for="contact-email">Contact email</label>
  <input id="contact-email" name="contact_email" type="email">
</form>
<form>
  <label for="newsletter-email">Newsletter email</label>
  <input id="newsletter-email" name="newsletter_email" type="email">
</form>

How to Find Duplicate IDs

  1. Open Chrome DevTools and open the Issues panel (the warning icon next to Console). Duplicate ids are reported as "A form field has duplicate id attributes".
  2. Run an automated accessibility checker (axe-core, for example) — duplicate ids are flagged as accessibility violations.
  3. Validate the page at validator.w3.org — it lists every duplicate id with line numbers.
  4. Run an automated audit and check the "[id] attributes on the page are unique" result under Accessibility.
  5. In any browser console, run this one-liner to list every duplicate id on the current page:
Array.from(document.querySelectorAll('[id]'))
  .map(el => el.id)
  .filter((id, i, a) => a.indexOf(id) !== i);

How to Fix and Prevent Duplicates

  • Scope ids to context: Prefer id="newsletter-email" over id="email".
  • Generate unique ids in components: In React, use useId(); in Vue, useId from Vue 3.5+.
  • Avoid id when class works: Most styling and event delegation does not need ids.
  • Audit on CI: Run axe-core in your test pipeline to catch regressions.
  • Watch third-party embeds: Wrap them in a container and scope your own ids to avoid collisions.

FAQ

Does the HTML spec actually require unique ids?

Yes. The HTML5 spec states the id attribute must be unique among all the IDs in the element's tree.

What does getElementById do when there are duplicates?

It returns the first element in tree order that has the matching id. The other elements are silently ignored.

Do duplicate ids affect SEO?

Not directly as a ranking signal. But broken in-page anchors, broken accessibility, and JS errors all degrade UX, which can affect engagement metrics.

Are duplicate ids a WCAG failure?

When they cause incorrect label or ARIA associations, yes — WCAG 1.3.1 (Info and Relationships) and 4.1.1 historically. WCAG 2.2 removed the standalone parsing requirement, but the underlying associations still must be correct.

How do I generate unique ids in React?

Use the useId hook from React 18+. It produces stable, unique ids that are safe across server and client rendering.

Is it a problem if duplicates are inside different shadow DOMs?

No. Shadow DOM creates a separate tree, so ids inside it do not collide with the main document.

What about querySelectorAll('#id')?

It returns all matches. But most code uses getElementById, which returns only the first.

Will browsers ever fix this by returning all matches?

No. The behavior is specified and changing it would break existing sites. Fix the duplicates instead.

Does this affect AI search engines like ChatGPT and Perplexity?

Indirectly, yes. AI search engines (ChatGPT, Perplexity, Google AI Overviews) preferentially cite well-ranked, well-structured pages, and duplicate ids confuse the accessibility tree and DOM landmarks those systems rely on to extract content. When labels and ARIA references resolve to the wrong element, AI extractors may pull mislabeled or mismatched answers from your page, lowering your odds of being cited cleanly.

Conclusion

Make every id unique. Run the one-line console snippet above to find duplicates today, then fix them by scoping names to context or generating ids with useId. Confirm with the "[id] attributes on the page are unique" audit and Chrome DevTools Issues panel. Run a Greadme deep scan to surface duplicate ids across your entire site in one pass and catch the templates and components that are the real source of regressions.