Start · Sprachen · JavaScript · Referenz · Highlight

Highlight

Schnittstelle

Stellt eine mengenartige Sammlung von <code>AbstractRange</code>-Objekten dar, die über <code>CSS.highlights</code> registriert und mit <code>::highlight()</code> gestylt werden.

seit JavaScript Chrome/Edge 105+, Safari 17.2+, Firefox 140+ Kategorie: webapi

Signatur

interface Highlight

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, Standard 0): 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

Typ
Highlight
Beschreibung
Der Konstruktor gibt ein neues 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));
1 true

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`);
});
z. B. "3 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);
(Text von Offset 4 bis 8) 0

// 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 Highlight allein ist unsichtbar. Es muss in CSS.highlights registriert und mit einer ::highlight(name)-Regel gestylt werden.
  • ::highlight() erlaubt nur wenige CSS-Eigenschaften, unter anderem color, background-color, text-decoration, text-shadow und -webkit-text-stroke. Eigenschaften, die das Layout ändern (font-size, padding, border …), werden ignoriert.
  • Range oder StaticRange: Ein Range ist „live“ und passt sich an, wenn sich das DOM ändert. Das ist bequem, kostet bei vielen Bereichen aber Leistung. Ein StaticRange ist günstiger, kann nach DOM-Änderungen aber auf falsche oder ungültige Stellen zeigen. Nach Änderungen sollte man ihn neu berechnen.
  • Die Eigenschaft type legt 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.