v158 · css · custom highlight api · cascade
Zero-specificity cascade
The spec’s subtle promise: the * argument contributes zero specificity, so a ::highlight(*) rule loses to any rule naming a specific highlight even when the universal rule comes later in source order. This page runs that experiment for real and reads the painted colour back with getComputedStyle(element, "::highlight(name)") — no trust required.
Experiment A — named vs named (works today)
Two rules name the same highlight with equal specificity, so the cascade’s source order decides. Flip the order and watch the painted colour follow the last rule — this is the behaviour the universal form must not show.
Experiment B — universal vs named (the Chrome 158 contract)
A ::highlight(*) rule paints yellow, a ::highlight(cascade-demo) rule paints blue. Whichever order you pick, the named blue must win — the universal rule has zero specificity and can only act as a base.
The text under test
Specificity is the tie-breaker the cascade consults before source order — and the universal highlight selector deliberately brings none of it.
The highlighted phrase carries the registered cascade-demo highlight; the readouts above report its computed background-color.
the readback
// Chrome exposes computed styles for highlight pseudo-elements:
const painted = getComputedStyle(sample, "::highlight(cascade-demo)")
.backgroundColor;
// Experiment B, order “named first, universal LAST”:
// equal specificity → last rule wins → yellow (WRONG for *)
// zero specificity(*) → named rule wins → blue (spec contract)