CSS Custom Highlight API: Performant Text Styling

The CSS Custom Highlight API provides a native, highly efficient mechanism to style arbitrary text ranges across a webpage without modifying the underlying DOM tree. By allowing JavaScript to manage text selections using standard Range objects and styling them declaratively using the CSS ::highlight() pseudo-element, developers can implement features like search results, syntax highlighting, and collaborative cursors without incurring the heavy layout and rendering costs of traditional DOM-wrapping techniques.

The Problem with Traditional Text Highlighting

Historically, styling specific text ranges required JavaScript to dynamically split text nodes and wrap target characters in HTML elements, such as <mark> or <span>. This approach introduces significant performance bottlenecks:

How the CSS Custom Highlight API Works

The CSS Custom Highlight API separates the logic of text selection from presentation through a four-step pipeline:

  1. Create Ranges: JavaScript identifies target text coordinates and generates standard DOM Range objects to define the start and end offsets within text nodes.

  2. Instantiate a Highlight: The ranges are passed into a Highlight object:

    const range = new Range();
    range.setStart(textNode, 0);
    range.setEnd(textNode, 5);
    
    const highlight = new Highlight(range);
  3. Register in the Highlight Registry: The Highlight instance is registered in the global CSS.highlights map with a custom identifier:

    CSS.highlights.set("search-result", highlight);
  4. Style via CSS: The designated identifier is targeted in CSS using the ::highlight() pseudo-element:

    ::highlight(search-result) {
      background-color: #ffeb3b;
      color: #000000;
    }

Why the API Is Performant

The performance advantages of the CSS Custom Highlight API stem from where and how the browser processes the styles: