4 min read

Be a master--the CSS Text Custom Highlight API

Table of Contents

Introduction

This week, let’s get hands-on with the CSS Custom Highlight API.

First, the Firefox browser has recently added support for this API. With all modern browsers now supporting it, it’s the perfect time to dive in and learn.

caniuse

Though labeled as a CSS API, its practical application requires developers with a solid foundation in JavaScript to effectively use it.

The good news is that it has several classic use cases, such as search highlights, with demo provided in the MDN documentation (as illustrated in Figure 1 below).

demo

OK, let’s start by showing how to DIY a custom text highlight effect.


Four Steps for Text Highlighting

To implement pure CSS text highlighting, you’ll need to follow these four steps:

  1. Create a Range object (using JavaScript);
  2. Use the Range object from step 1 to create a Highlight object (using JavaScript);
  3. Register the Highlight object with the HighlightRegistry method (using JavaScript);
  4. Apply the registered text selection styles using the ::highlight() pseudo-element (using CSS).

As you can see, the majority of the work in the CSS Custom Text Highlight API is done by JavaScript.

Let’s walk through a practical example using these four steps to create a text highlight effect. For a unique scenario, let’s highlight phone numbers on the page, keeping them hidden from plain view.

Here’s the HTML:

<p id="p">That Google contact team can be reached at 1-800-419-0157.</p>

The goal is to achieve the following effect:

This can be done in four steps:

1. Create a range

Use the new Range() statement to construct the range, then set its start and end positions.

const str = p.textContent;
const regex = /\d{3}-\d{3}-\d{4}/;
const arrIndex = str.match(regex).map(tel => str.indexOf(tel));
const arrRange = arrIndex.map(start => {
    const range = new Range();
    range.setStart(p.firstChild, start + 4);
    range.setEnd(p.firstChild, start + 7);
    return range;
});

2. Create a Highlight object

The syntax for the new Highlight() method is as follows:

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

Therefore, we can proceed as follows:

const highlight = new Highlight(...arrRange.flat());

3. Register the highlight

This is straightforward and can be done in just one line of code:

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

4. CSS Apply Highlight

Now the ::highlight() pseudo-element comes into play. The parameter is the highlight name registered in step 3 above:

::highlight(tel-highlight) {
  background-color: currentColor;
}

At this point, you can see the effect as shown in the image, where the middle three digits of the phone number are turned into colored blocks and become invisible.

result


Additional Notes and Conclusion

In actual development, creating a range is more complex than in the example above because the highlighted element contains many mixed elements and nodes. A more complex traversal algorithm is required. For further details, refer to the two examples provided at the beginning of this article.

The ::highlight() pseudo-element does not support CSS variables. For example:

::highlight(highlight) {
  --color: red;
  color: var(--color);
}

This will not highlight the text in red.

The ::highlight() pseudo-element only supports a limited set of CSS properties, including:

  • Text color (color)
  • Background color (background-color)
  • Text decoration (text-decoration)
  • Text shadow (text-shadow)
  • Text stroke (-webkit-text-stroke)
  • Text fill color (-webkit-text-fill-color)

This means that we cannot change the font size of highlighted text (though size-adjust can be used), but we can apply text shadows, underlines, strokes, and more.

Highlighted text cannot respond to events and can only be used for pure style changes. If event handling is needed, it is better to use the traditional method of wrapping with tags.