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.
id="add-to-cart" on its button. Render 12 product cards on a category page and you have 12 elements with that ID.
# 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.
If the duplicate ID isn't referenced by anything (no JS, no label, no anchor), just remove it. Classes work for styling.
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>
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.
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);
});
#add-to-cart { ... } with .add-to-cart { ... }. Classes work for styling; IDs aren't needed.
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">