/ HTML Checker Fixes / Duplicate IDs

How to Fix Duplicate HTML IDs

HTML IDs must be unique per document. Browsers tolerate duplicates with error-recovery rules — getElementById returns the first match, label-for points at the first match, CSS applies to all — but the bugs that result are subtle. Form fields submit wrong values. Click handlers fire on the wrong element. Anchor links jump to the wrong section. This guide walks through audit, safe renaming, and prevention.

1. Run the HTML Checker

Step 1
Get the duplicate list
Run the HTML Checker. Filter to duplicate-ID errors. Each finding shows the ID value, how many times it appears on the page, and the element types.
Step 2
Group by component
Duplicate IDs almost always come from a reusable component rendered multiple times on the same page. Example: a "product-card" template with id="add-to-cart" on its button. Render 12 product cards on a category page and you have 12 elements with that ID.

2. Audit every reference before renaming

⚠️ Renaming an ID without updating its references breaks things silently. Always grep the codebase first.
Step 1
Search for the ID across the codebase
# Find every JS reference
grep -rE 'getElementById.{0,3}("|'"'"')add-to-cart\1' src/

# Find every CSS reference  
grep -rE '#add-to-cart' src/

# Find every label-for reference
grep -rE 'for="add-to-cart"' src/

# Find anchor references
grep -rE 'href="#add-to-cart"' src/
Note every file and line. These all need updating when you rename.

3. Pick a renaming strategy

Option A: Strip the ID entirely (best when not actually needed)

If the duplicate ID isn't referenced by anything (no JS, no label, no anchor), just remove it. Classes work for styling.

Option B: Parameterise by component instance

Add a suffix from a unique context value:

<!-- WordPress / PHP -->
<button id="add-to-cart-<?php echo $product->id; ?>">Add to cart</button>

<!-- Liquid (Shopify) -->
<button id="add-to-cart-{{ product.id }}">Add to cart</button>

<!-- React JSX -->
<button id={`add-to-cart-${product.id}`}>Add to cart</button>

Option C: React useId hook

import { useId } from 'react';

function ProductCard() {
  const id = useId();
  return (
    <form>
      <label htmlFor={id}>Quantity</label>
      <input id={id} type="number" />
    </form>
  );
}

useId generates a unique stable ID per component instance. Best for component libraries that need IDs but don't know how many instances will render.

4. Update every reference

Step 1
Update JS selectors
Replace document.getElementById('add-to-cart') with event delegation or a class-based selector:
// BEFORE
document.getElementById('add-to-cart').addEventListener('click', handleClick);

// AFTER (event delegation)
document.addEventListener('click', (e) => {
  if (e.target.matches('.add-to-cart')) handleClick(e);
});
Step 2
Update CSS selectors
Replace #add-to-cart { ... } with .add-to-cart { ... }. Classes work for styling; IDs aren't needed.
Step 3
Forms must use unique IDs because label for= points at a specific element. If you parameterised by instance:
<label for="quantity-<?php echo $product->id; ?>">Quantity</label>
<input id="quantity-<?php echo $product->id; ?>" type="number">

5. Re-validate

Step 1
Run the HTML Checker
Duplicate-ID count should drop to zero. Any remaining duplicates indicate a component you missed or content with hardcoded IDs in CMS rich-text.
Step 2
Test interactive behaviour
Click every button that previously used the duplicate ID. Submit every form. Test anchor links. Renaming usually catches most issues but visual testing catches what greps miss.
💡 For new templates and components, default to classes for styling and JS hooks. Use IDs only when uniqueness is structurally required (form labels, in-page anchors). Prevention beats audit-after.

📐 Re-run the HTML Checker

Verify duplicate-ID count is zero after renaming.

Run HTML Checker →
Related Guides: HTML Checker Fixes  ·  Fix ARIA Errors  ·  Fix Form Validation  ·  HTML Checker Guide
💬 Got a problem?