Hauptansätze zur Texthervorhebung

Hauptansätze zur Texthervorhebung


Texthervorhebung mag auf den ersten Blick einfach erscheinen—einfach den Hintergrund auf Gelb ändern—aber es ist eigentlich ziemlich komplex. Nehmen Sie dieses Beispiel unten, wo der hervorgehobene Teil mehrere Elemente umspannt und teilweise Text von darunterliegenden Elementen enthält.

Highlights across elements

Im Folgenden gehe ich durch verschiedene gängige Ansätze zur Implementierung von Texthervorhebung, diskutiere deren Vor- und Nachteile zusammen mit praktischen Anwendungsfällen, um die wichtigsten technischen Lösungen zu skizzieren.

CSS Highlight API — Moderne und effiziente Texthervorhebung

Dies ist derzeit die beste Wahl für die Implementierung von Texthervorhebung, da sie einfach zu verwenden und leistungsstark ist. Der einzige Nachteil ist, dass Browser relativ neue Versionen für die Unterstützung benötigen, obwohl bis 2025 alle wichtigen Browser sie unterstützen.

Highlight-Objekt

Zuerst müssen Sie für jeden hervorgehobenen Bereich ein Range-Objekt erstellen. Range ist eine langjährige API, die einen kontinuierlichen Abschnitt im DOM-Baum darstellt—falls Sie damit nicht vertraut sind, müssen Sie sich damit vertraut machen.

const range = new Range();
range.setStart(someNode, startOffset);
range.setEnd(someNode, endOffset);

Dann fügen Sie es zu einem Highlight-Objekt hinzu. Da Hervorhebung mehrere nicht zusammenhängende Bereiche haben kann, kann ein einzelnes Highlight-Objekt mehrere Ranges enthalten.

const highlight = new Highlight(range1, range2, ..., rangeN);

Es ist ähnlich wie ein Set-Objekt, daher können Sie Methoden wie add, delete, etc. verwenden, um die enthaltenen Ranges zu modifizieren.

CSS.highlights

Dann fügen Sie das Highlight-Objekt zu CSS.highlights hinzu. Es ist ähnlich wie ein Map-Objekt mit Methoden zum Hinzufügen und Entfernen von Mitgliedern wie get, set, delete, etc. und den gleichen Iterationsmethoden.

Genau wie eine Map müssen Sie beim Hinzufügen eines Highlights einen Schlüssel als Namen des Highlights angeben. Dieser Name ist sehr nützlich—wie wir unten sehen werden, verwenden wir diesen Namen, um den Hervorhebungsstil festzulegen, wie einen grünen Hintergrund. Also haben alle Hervorhebungen im gleichen Highlight-Objekt den gleichen Stil. Wenn Sie ein anderes Textstück in Blau hervorheben möchten, müssen Sie ein neues Highlight erstellen.

CSS.highlights.set("my-highlight", highlight);

Pseudo-Element ::highlight definieren

Als nächstes kommen die CSS-Stile ins Spiel. Sie können Hervorhebungsstile mit dem Pseudo-Element ::highlight(highlight-name) definieren.

::highlight(my-highlight) {
  background-color: yellow;
  color: black;
}

Hinweis: Nur wenige CSS-Eigenschaften können verwendet werden, wie background-color, color, cursor, etc. Siehe die Spezifikation für Details.

Hervorhebungsbereiche dynamisch modifizieren

CSS.highlights ist wie eine Map mit ähnlichen Methoden zum Aktualisieren von Highlights:

  • CSS.highlights.clear()
  • set(highlightName, Highlight)
  • delete(highlightName)

Das Highlight-Objekt ist wie ein Set mit ähnlichen Methoden zum Aktualisieren von Ranges:

  • Highlight.add(range)
  • delete(range)

Text-Element-Stile modifizieren

Erreichen Sie Hervorhebung durch Durchsuchen des DOM, um Zieltextknoten zu finden und deren Hintergrundstile direkt zu modifizieren.

  • Erfordert DOM-Modifikationen, die Browser-Reflow mit erheblicher Leistungsüberlastung verursachen.
  • Implementierung von übergreifender Elementhervorhebung (wo der Hervorhebungsbereich mehrere Elemente umspannt) ist ziemlich komplex. Highlights across elements
  • Geeignet für Szenarien, wo hervorgehobener Inhalt relativ fest ist und der Bereich klein ist.

Zusätzliche Ebenen überlagern, um Hervorhebungen zu rendern, ohne Text-DOM zu ändern

Erstellen Sie eine transparente Überlagerungsebene, berechnen Sie die Bildschirmposition des Zieltexts, dann zeichnen Sie halbtransparente Hervorhebungen auf der Überlagerung.

Hervorhebungsbereiche positionieren

  • Verwenden Sie Element.getClientRects() oder getBoundingClientRect(), um Textkoordinaten auf der Seite zu erhalten.
  • Bei der Behandlung von mehrzeiligem Text entspricht jede Zeile einem rechteckigen Bereich, der separate Hervorhebungsblöcke benötigt.
  • Fenstergrößenänderungen oder Schriftgrößenänderungen erfordern eine Neuberechnung der Hervorhebungspositionen, was die Leistung beeinträchtigen kann.

Hervorhebungs-Zeichenmethoden

DIV als Überlagerung

Verwenden Sie absolut positionierte übergeordnete Container und halbtransparente Hintergrund-Kindelemente, um Text zu überlagern. Zum Beispiel verwendet der Monaco-Editor diesen Ansatz, um gleiche Worthervorhebung zu implementieren.

<div class="editor" style="position: relative;">
  <div class="overlay" style="position: absolute; height: 0;">
    <div
      class="highlight"
      style="top:0; left:57px; width:23px; background-color: rgba(173,214,255,0.15);"
    ></div>
    <!-- Weitere Highlight-Bereiche hinzufügen -->
  </div>
  <div class="content">
    <!-- Textinhalt -->
  </div>
</div>
  • Die Position des Overlays ist absolute, während sichergestellt wird, dass das übergeordnete Element nicht position: static ist, damit absolute Positionierung funktioniert. Dies ermöglicht es, dass interne Hervorhebungselemente überall positioniert werden können.
  • Um über Text zu platzieren, setzen Sie einfach das Overlay vor dem Textcontainer in HTML. Die Overlay-Höhe ist 0, um die Interaktion mit darunterliegendem Text nicht zu beeinträchtigen.
  • Fügen Sie Elemente hinzu, setzen Sie background-color auf halbtransparente Hervorhebungsfarbe, positionieren Sie an der hervorgehobenen Textposition und setzen Sie die Breite.
  • Der Monaco-Editor (VSCode basiert darauf) verwendet diese Methode. Siehe die offizielle Demo. Nach der Auswahl eines Schlüsselworts werden die gleichen Schlüsselwörter hervorgehoben. Beim Betrachten des HTML werden Sie feststellen, dass diese Schlüsselwörter ihre Stile nicht geändert haben, aber es gibt ein Overlay auf der Editor-Oberfläche mit halbtransparenten Hervorhebungsfarben, die innen gezeichnet sind (siehe das div mit class="view-overlays").

SVG als Überlagerung

  • Setzen Sie Overlay auf die gleichen Dimensionen wie die Seite
  • Fügen Sie <rect> hinzu, dann zeichnen Sie an hervorgehobenen Textpositionen
  • foliate-js verwendet diese Methode. Siehe overlayer.js.

Selection API und ::selection Pseudo-Element verwenden — Standard-Textauswahlhervorhebung des Browsers

Browser heben natürlich ausgewählten Text hervor, daher kann die Steuerung der Auswahl indirekt Hervorhebung erreichen. Stile können über das CSS-Pseudo-Element ::selection angepasst werden.

const range = new Range();
range.setStart(parentNode, startOffset);
range.setEnd(parentNode, endOffset);

// Auswahl setzen
const selection = document.getSelection();
selection.removeAllRanges();
selection.addRange(range);
::selection {
  background-color: #c3c2c2;
  color: white;
}

Diese Methode ist ziemlich clever, einfach und hat breite Browser-Unterstützung, hat aber einen großen Nachteil: Da nur eine Auswahl gleichzeitig existieren kann, werden programmatische Auswahlen und tatsächliche Benutzerauswahlen in Konflikt geraten und sich gegenseitig überschreiben. Daher ist sie nur für Szenarien geeignet, die die folgenden Bedingungen erfüllen:

  • Benutzer können Text nicht auswählen
  • Es gibt nur ein kontinuierliches hervorgehobenes Textsegment
  • Sie müssen ältere Browser unterstützen
  • Sie wollen faul sein und andere Methoden vermeiden