Direct answer: the 25 homepages carry 1,765 id attributes; 10 sites contain duplicates, with 48 duplicated names and 849 extra occurrences. The worst are E03 (233 extras), E22 (154), E06 (149), E14 (120) and E23 (105); E17 has eight duplicate names but only ten extras. The pages hold just four label for and ARIA references, all of which resolve (zero dangling). A post-render recheck (15 renderable sites) found 12 sites adding ids and E26 growing from 2 duplicate names / 17 extras to 4 names / 33 extras — a JavaScript clone copies ids; ten sites failed to render and are excluded. On the reference side, the 25 pages hold four page references, all resolving, and 183 inline-script id lookups include one duplicate hit (E11 count-number).

The analysis strips <script>, <style> and comments first, so id="…" strings inside JavaScript templates do not inflate the counts; only static HTML is counted.

1,765
id attributes
10
sites with duplicates
48
duplicate names
849
extra occurrences
4
label/ARIA references
0
dangling references

Method: strip scripts, then count static ids

On 2026-11-09 between 13:41 and 13:42 we requested the HTML of the same 25 cached-200 homepages, removed <script>, <style> and HTML comments, then extracted id="…" and counted duplicate names. We also collected ids referenced by label for and aria-labelledby/describedby/controls/owns/activedescendant and checked whether they exist in the document.

MeasureRuleBoundary
id attributeOccurrences of id="…" in static HTMLStrings in scripts, styles and comments excluded
Duplicate nameA name appearing more than onceCase compared as written
Extra occurrencesSum of (count − 1) for each duplicate nameNot the number of duplicate names
Referencelabel for plus aria idrefsExistence only, order not checked
Dangling referenceTarget id absent from the documentA duplicated target still counts as present

Result: ten sites repeat, a few heavily

MeasureCountSites
id attributes1,76524
Duplicate names4810
Extra occurrences84910
label / ARIA references41
Dangling references00
SiteidsDuplicate namesExtra occurrences
E033297233
E221866154
E061725149
E141774120
E232957105
E0987248
E2639217
E1774810
E111417
E249066

Two shapes appear: E03, E22, E06, E14 and E23 repeat one id hundreds of times, typical of a carousel or card template that keeps a fixed id inside a loop; E17 and E24 repeat several different ids a few times, more like a component rendered twice on the page. The first shape is more likely to make getElementById and fragment links hit the wrong element.

Counting again after rendering: one site adds duplicates

On 2026-11-09 between 14:41 and 14:45 we captured the rendered DOM of the 25 sites with headless Chrome (--dump-dom, 15-second virtual time, a separate profile per site) and applied the same id rules. Fifteen sites rendered; ten were excluded for 403, challenge pages or timeouts.

Measure (15 renderable sites)StaticRendered
Total ids3431,162
Duplicate names1113
Extra occurrences3450
Sites with duplicates33
E26 extra occurrences1733

Twelve sites change their id count after rendering: E02 goes from 6 to 644 (all unique), E25 7→133, E26 39→57 and E18 1→17; E28 drops from 1 to 0, meaning a script rewrote the DOM. E26 is the only site that gains duplicates: duplicate names 2→4 and extra occurrences 17→33, direct evidence that a JavaScript clone copies ids; E11 and E17 keep the same duplicates before and after, so theirs come from the static template. Sites with the heaviest static duplicates — E03, E06, E14, E22, E23 and E24 — did not render this time, so they cannot be compared.

Reference side: 4 page references and 183 script id lookups, one duplicate hit

Whether a duplicate id matters depends on who references it. On 2026-11-09 between 17:42 and 17:43 we fetched the same 25 homepages as static HTML again and parsed label for, ARIA idrefs and real href="#id" anchors, then scanned inline scripts for literal getElementById, querySelector('#id') and jQuery $('#id') calls.

Reference kindCountPoints at a duplicateDangling
label for / ARIA idrefs400
href="#id" anchor000
Inline-script id lookup183 (18 sites)1—

The only hit is E11: the page has eight id="count-number" elements, so jQuery's #count-number reaches only the first p.timer.count-title and the other seven never update; the remaining 182 lookups point at unique names. Of the 48 duplicated names, just this one is referenced by a static script, and there are no page anchors — the risk is latent rather than widespread here.

Rule fix: onclick="this.href='#x'" is not a static anchor, and both the probe and the id checker now exclude it; E04 generates skip links in script and targets <a name>, so those are not counted as id references.

What this means for acceptance

  1. Add id uniqueness to HTML validation. Ten of 25 sites fail it, and most validators catch it with one rule.
  2. Rewrite ids when cloning a component. One name on E03 repeats over two hundred times; append an index in template loops or switch to a class.
  3. Use classes for styling hooks. Ids written only to attach styles are the ones that collide when copied.
  4. Check anchors and ARIA targets. Duplicate ids point fragments and aria references at the first element; references are few here, but the risk remains.
  5. Repeat the check after rendering. In the 15-site recheck, E26 moved from 2 to 4 duplicate names; static uniqueness does not imply runtime uniqueness, so rerun after cloning components. The id uniqueness checker reruns the rules locally in a browser; see also the website development service.

Limits

  • Static HTML only: scripts, styles and comments are stripped; runtime ids are not counted.
  • Regex approximation: no DOM is built; case is compared as written.
  • Reference scope: pages cover label for, ARIA idrefs and static href="#id" anchors; scripts cover literal inline getElementById/querySelector/jQuery calls, not external bundles or concatenated ids.
  • Existence rule: a duplicated id still counts as present, so pointing at the wrong element is not flagged.
  • Script hit: it means the selector reaches the first same-name element only; the page script is not executed and the intended element is not judged.
  • Render boundary: 15 of 25 sites rendered; ten were excluded for 403, challenge pages or timeouts, and 15 seconds of virtual time cannot see later asynchronous insertion.
  • 25-site pilot: the same equipment-company sample; no industry claim.

Data and reproduction

Anonymised data: equipment-homepage-id-uniqueness-2026.csv (25 rows × 8 columns: ids, duplicate names, extra occurrences, references/dangling and time). The repository keeps docs/research/2026-11-homepage-id-uniqueness.csv.

Rendered recheck: equipment-homepage-id-runtime-2026.csv (25 rows × 14 columns: render status, static and rendered ids, duplicates, extra occurrences and time). The repository keeps docs/research/2026-11-homepage-id-runtime.csv.

Reference recheck: equipment-homepage-id-references-2026.csv (25 rows × 16 columns: page references, script id lookups, duplicate hits and time). The repository keeps docs/research/2026-11-homepage-id-references.csv.

Parser: scripts/id_uniqueness_probe.py; unit tests: scripts/test_content_id_uniqueness_probe.py (8, offline); reference and script scans are in scripts/test_content_id_reference_probe.py (13 tests). Run:

python -m unittest scripts.test_content_id_uniqueness_probe

Related: the homepage template-hygiene audit, the homepage script-hygiene audit, and homepage semantics, keyboard access and ARIA.

Sources and definitions

  1. Sample: the 25 study-4 homepages cached as 200.
  2. Fetch: 2026-11-09 13:41–13:42 Asia/Shanghai, serial, 0.5 s apart, 15-second timeout.
  3. Preprocessing: scripts, styles and comments removed before extracting ids.
  4. References: label for and aria idrefs; existence only, order not checked.

Frequently asked questions

How serious are duplicate ids?

They are an HTML validation error and make getElementById, fragment links and ARIA targets resolve to the first match only; cloned widgets hit this most often.

Is 1,765 ids a lot?

The count is not the issue; uniqueness is. Component anchors, forms and SVG all use ids, and the problems concentrate on a few sites with repeated names.

Does zero dangling references mean it is fine?

No. Only four label/ARIA references exist here, and duplicate ids can point a reference at the wrong element — “exists” is not “correct”.

Why are script-generated ids excluded?

The analysis strips <script> blocks first and counts static HTML; ids created at runtime need a post-render check.

How should it be fixed?

Prefix component ids or add an index, and rewrite ids when cloning a template; use classes or data attributes when the id is only a styling hook.

Can the data be re-checked?

Yes. The public CSV has 25 rows by 8 columns, and scripts/id_uniqueness_probe.py has 8 offline unit tests.

Do duplicates grow after rendering?

Sometimes, but only one site here. Among the 15 renderable sites, E26 moves from 2 to 4 duplicate names and from 17 to 33 extra occurrences; the rest stay flat or add only unique ids.

Do duplicate ids break scripts immediately?

Not necessarily. Of 183 inline-script id lookups across the 25 sites, one hits a duplicated name (E11 count-number, eight copies); a duplicate id is a latent risk waiting for a reference, not an automatic failure. External bundles, dynamic id strings and runtime insertion are out of scope.

About the author

Lingyi Information Official (delivery team) works on requirements, proposals and acceptance for corporate websites, brand and smart-manufacturing projects. This article counts id attributes, page references and inline script literals in static HTML; it does not execute page scripts or build a DOM; ten sites have duplicates and the sample is a pilot.

Ids must be unique too

Duplicate ids are invisible, yet they send fragments, labels and scripts to the first element only.

Request a recheck plan