Signatur
Beschreibung
Das Interface Highlight ist das Kernstück der CSS Custom Highlight API. Ein Highlight-Objekt fasst beliebig viele Range- oder StaticRange-Objekte zusammen. Registriert man es unter einem Namen in der HighlightRegistry (CSS.highlights.set(name, highlight)), kann man diese Textbereiche per CSS mit dem Pseudo-Element ::highlight(name) einfärben. Dabei wird das DOM nicht verändert: Es entstehen keine zusätzlichen <span>- oder <mark>-Elemente.
Typische Einsatzfälle sind Suchtreffer-Hervorhebung, Syntax-Highlighting in Code-Editoren, Markierungen bei kollaborativem Bearbeiten (Cursor und Auswahl anderer Nutzer), Anmerkungen oder eigene Rechtschreibprüfungen. Weil das DOM unverändert bleibt, ist das deutlich schneller und robuster als das Einfügen von Wrapper-Elementen, und es kommt nicht zu Konflikten mit Frameworks wie React oder Vue, die das DOM selbst verwalten.
Highlight verhält sich wie ein Set (setlike): Es gibt add(), delete(), has(), clear(), forEach(), entries(), keys(), values(), die Eigenschaft size und Iteration mit for...of. Außerdem gibt es zwei Eigenschaften:
priority(number, Standard0): Wenn sich Highlights überlappen, bestimmt der Wert, welches oben liegt. Höhere Werte gewinnen; bei gleichem Wert zählt die Reihenfolge der Registrierung.type("highlight"|"spelling-error"|"grammar-error", Standard"highlight"): Hilfsmittel wie Screenreader können daran erkennen, was die Hervorhebung bedeutet.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $...ranges | AbstractRange[] (Range | StaticRange) | Parameter des Konstruktors new Highlight(...ranges): null oder mehr Bereiche, mit denen das Highlight gleich zu Beginn gefüllt wird. |
Rückgabewert
Highlight-Objekt zurück. Sichtbar wird es erst, wenn es mit CSS.highlights.set() registriert und per ::highlight() gestylt wird.Beispiele
Highlight anlegen, registrieren und stylen
// CSS: ::highlight(markiert) { background-color: yellow; color: black; }
const absatz = document.querySelector('p');
const textNode = absatz.firstChild;
const range = new Range();
range.setStart(textNode, 0);
range.setEnd(textNode, 5);
const highlight = new Highlight(range);
CSS.highlights.set('markiert', highlight);
console.log(highlight.size, highlight.has(range));
Suchtreffer ohne DOM-Änderung hervorheben
// CSS: ::highlight(suche) { background-color: orange; }
const sucheHervorheben = (wurzel, begriff) => {
CSS.highlights.delete('suche');
if (!begriff) return 0;
const walker = document.createTreeWalker(wurzel, NodeFilter.SHOW_TEXT);
const treffer = new Highlight();
const suchwort = begriff.toLowerCase();
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
const text = node.textContent.toLowerCase();
let index = text.indexOf(suchwort);
while (index !== -1) {
treffer.add(new StaticRange({
startContainer: node, startOffset: index,
endContainer: node, endOffset: index + suchwort.length
}));
index = text.indexOf(suchwort, index + suchwort.length);
}
}
CSS.highlights.set('suche', treffer);
return treffer.size;
};
document.querySelector('#suchfeld').addEventListener('input', (e) => {
const anzahl = sucheHervorheben(document.querySelector('article'), e.target.value);
console.log(`${anzahl} Treffer`);
});
Überlappende Highlights mit priority und type steuern
// CSS:
// ::highlight(fehler) { text-decoration: wavy underline red; }
// ::highlight(auswahl) { background-color: lightblue; }
const node = document.querySelector('#editor').firstChild;
const r1 = new Range();
r1.setStart(node, 0);
r1.setEnd(node, 10);
const r2 = new Range();
r2.setStart(node, 4);
r2.setEnd(node, 8);
const auswahl = new Highlight(r1);
const fehler = new Highlight(r2);
fehler.type = 'spelling-error'; // semantischer Hinweis für Hilfsmittel
fehler.priority = 1; // liegt über 'auswahl'
CSS.highlights.set('auswahl', auswahl);
CSS.highlights.set('fehler', fehler);
for (const r of fehler) console.log(r.toString());
// Später aufräumen
fehler.clear();
console.log(fehler.size);
// Wichtig · Fallstricke
- Browser-Unterstützung: Chromium ab 105, Safari ab 17.2, Firefox erst ab 140. Vorher per
if ('highlights' in CSS)prüfen und notfalls auf<mark>-Elemente ausweichen. - Ein
Highlightallein ist unsichtbar. Es muss inCSS.highlightsregistriert und mit einer::highlight(name)-Regel gestylt werden. ::highlight()erlaubt nur wenige CSS-Eigenschaften, unter anderemcolor,background-color,text-decoration,text-shadowund-webkit-text-stroke. Eigenschaften, die das Layout ändern (font-size,padding,border…), werden ignoriert.- Range oder StaticRange: Ein
Rangeist „live“ und passt sich an, wenn sich das DOM ändert. Das ist bequem, kostet bei vielen Bereichen aber Leistung. EinStaticRangeist günstiger, kann nach DOM-Änderungen aber auf falsche oder ungültige Stellen zeigen. Nach Änderungen sollte man ihn neu berechnen. - Die Eigenschaft
typelegt nur die Bedeutung fest, nicht das Aussehen. Auch bei"spelling-error"muss man selbst stylen. Wie Screenreader den Wert nutzen, unterscheidet sich zwischen Browsern. - Ein
Highlight-Objekt lässt sich unter mehreren Namen registrieren. Änderungen daran wirken sich dann auf alle diese Namen aus.