Agent Wranglers

Required

Keep ids unique and stable

Give each id on a page a value that appears once on that page and stays the same in every build. Make it from the content or the data key, never from a counter or a random number.

How to do it

Links such as /menu#rye-loaf, labels, aria-controls and tests all point at ids. A counter changes the id when a section is added above it, and the old links break. Build the id from a slug of the heading or the record's key, and add the module prefix when two modules could clash. Ids are never used for styling, as Never style by id requires.

Examples

Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

JavaScript example

const ids = [...html.matchAll(/\sid="([^"]+)"/g)].map(([, id]) => id);
const duplicates = ids.filter((id, i) => ids.indexOf(id) !== i);
if (duplicates.length) throw new Error(`${path}: duplicate ids ${[...new Set(duplicates)].join(', ')}`);

Python example

import re
from collections import Counter
ids = re.findall(r'\sid="([^"]+)"', html)
duplicates = [i for i, count in Counter(ids).items() if count > 1]
if duplicates:
    raise SystemExit(f"{path}: duplicate ids {', '.join(duplicates)}")

HTML example

<!-- Avoid: changes when a section is added above -->
<section id="section-3">
<!-- Do: made from the content -->
<section id="menu-rye-loaf">

How to check

Every built page has 0 duplicate ids. Two builds of the same content produce the same list of ids on every page.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. Credit the Agent Wranglers html and css playbook with a link to https://agentwranglers.se/playbook/html-css/html-structure-and-reuse/unique-stable-ids. Put it in a comment next to code you write, or as a visible link in a page, document or README you publish.