demo · v134

Custom Highlight API

The CSS Custom Highlight API + the new inheritance rules. Toggle independent highlight registries (spell, grammar, todo, quote-callout), watch them layer on the same text, and see how ::highlight() now inherits properties through the highlight chain instead of the element chain.

painting priority

3
7

Enable spell + grammar to compare the overlapping priority word.

Editor view

The browser doesn't pre-highlight any of teh mistakes here — that's the editor's job. Each toggle above registers a different Highlight instance over the same DOM range. The word priority is deliberately covered by both spell and grammar so the sliders can change which paint wins.

A subject verb-agreement issues happens in this sentence. Grammar layer above.

The TODO: link to RFC 8941 here kind of marker is its own highlight. Different colour, no underline.

Quoted text — when the quote highlight is on, the inheriting cascade picks up properties from the document highlight while letting .quote::highlight(quote) override only background-color.
CSS.highlights.set("spell", new Highlight(range1));
CSS.highlights.set("grammar", new Highlight(range2));
CSS.highlights.set("todo", new Highlight(range3));
CSS.highlights.set("quote", new Highlight(range4));

// This demo uses selectNodeContents() for whole-node ranges.
// Editors usually use range.setStart(textNode, startOffset)
// and range.setEnd(textNode, endOffset) for character-precise spans.

.doc::highlight(spell) {
  background: color-mix(in srgb, var(--accent-rose) 18%, transparent);
  text-decoration: underline wavy var(--accent-rose);
}
.doc::highlight(grammar) { ... }
.doc::highlight(todo) { ... }
.doc::highlight(quote) {
  background: color-mix(in srgb, var(--accent-emerald) 18%, transparent);
  color: var(--accent-emerald);
}
.doc .quote::highlight(quote) {
  background: color-mix(in srgb, var(--accent-emerald) 30%, transparent);
}
/* color inherits from .doc::highlight(quote) — the v134 win */

why inheritance matters here

An editor surface stacks highlight registries: spell, grammar, comments, search-match, todo, suggestion, conflict. Before v134, each registry that styled only one property (say, background) would silently lose any text-colour rule defined higher up the document. You'd have to repeat every property at every nesting level.

With highlight inheritance, you set the body-level ::highlight(spell) once and let nested elements override only the bits they want. Less CSS, no surprises, much closer to how authors expect cascading to work.

see also