CSS ::highlight() Pseudo-Element

The ::highlight() pseudo-element styles custom text ranges registered through the CSS Custom Highlight API. It allows developers to highlight specific words or portions of text without adding extra HTML elements, making it useful for search results, annotations, and text highlighting tools.

Syntax

::highlight(highlight-name) {
  property: value;
}

The ::highlight() pseudo-element accepts a custom highlight name as its argument.

The name identifies a highlight registered using JavaScript.

For example:

::highlight(search-result) {
  background-color: #fff2a8;
  color: #222;
}

This rule requests a light yellow background and dark text for ranges registered under the name search-result.

The highlight name is a CSS identifier and is not enclosed in quotation marks.

The corresponding JavaScript registration uses the same name:

CSS.highlights.set("search-result", highlight);

The highlight variable must contain a Highlight object representing one or more text ranges.

Important: CSS alone does not create custom highlight ranges. JavaScript is required to identify the ranges and register them.

How It Works

The ::highlight() pseudo-element works with the CSS Custom Highlight API.

The process involves four steps:

  1. Identify the text that should be highlighted.
  2. Create a JavaScript Range representing that text.
  3. Register the range using a Highlight object and CSS.highlights.
  4. Style the registered highlight using ::highlight().

For example, a webpage might contain the following paragraph:

<p id="highlight-text">CSS makes styling webpages easier.</p>

JavaScript can select the word "styling" and register it as a custom highlight.

The CSS rule then determines how that selected text appears.

Unlike wrapping the word in a <span>, the Custom Highlight API does not require changing the paragraph's HTML structure.

The highlight is a visual decoration applied to a text range.

CSS Custom Highlight API

The CSS Custom Highlight API provides JavaScript interfaces for defining and managing custom text highlights.

Its primary components include:

Component Purpose
Range Identifies a portion of content within the document.
Highlight Groups one or more ranges into a custom highlight.
CSS.highlights Provides a registry for named custom highlights.
::highlight() Applies CSS styling to registered highlight ranges.

The API separates text selection from visual styling.

JavaScript determines which ranges are highlighted, while CSS controls their appearance.

This approach is useful when highlighted text changes dynamically, such as when users search for words within a document.

Because the original HTML remains unchanged, the API avoids inserting and removing wrapper elements for each highlighted match.

Creating a Text Range

A JavaScript Range represents a portion of content within the document.

For example:

<p id="range-example">Learn CSS selectors.</p>

The following JavaScript selects the word "CSS":

const paragraph = document.getElementById("range-example");
const textNode = paragraph.firstChild;
const range = document.createRange();
range.setStart(textNode, 6);
range.setEnd(textNode, 9);

The document.createRange() method creates a new range.

The setStart() method defines where the range begins.

The setEnd() method defines where the range ends.

In this example, offsets 6 through 9 identify the letters in "CSS".

Range offsets are measured within the text node and use UTF-16 code units.

The range identifies the text but does not highlight it visually until it is registered and styled.

Registering a Highlight

After creating a text range, use the Highlight constructor to create a custom highlight.

const highlight = new Highlight(range);

The Highlight object stores the range.

Next, register it with a custom name:

CSS.highlights.set("important-text", highlight);

The name important-text identifies the highlight in the registry.

CSS can now target the registered highlight:

::highlight(important-text) {
  background-color: #fff2a8;
  color: #222;
}

The registered text range receives the specified styling in supporting browsers.

Registering a highlight does not add a new element to the document.

Multiple ranges can be included in the same Highlight object.

Styling Custom Highlights

The ::highlight() pseudo-element supports a restricted set of CSS properties designed for styling text highlights.

Changing the Background Color

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

This rule gives registered text ranges a light yellow background.

Changing the Text Color

::highlight(search-result) {
  color: #0066cc;
}

This rule changes the text color of the highlighted ranges.

Adding an Underline

::highlight(search-result) {
  text-decoration: underline;
  text-decoration-color: #cc3300;
}

This rule requests an underline with a reddish-orange decoration color.

Combining Styles

::highlight(search-result) {
  background-color: #fff2a8;
  color: #222;
  text-decoration: underline;
  text-decoration-color: #cc3300;
}

These declarations combine background highlighting with text and underline styling.

Unlike ordinary elements, custom highlight pseudo-elements do not support general layout properties such as padding, margin, or border.

Example

The following example highlights the word "CSS" inside a paragraph without changing the HTML markup.

HTML:

<p id="custom-highlight-example">Learning CSS makes web design easier and more flexible.</p>

CSS:

::highlight(css-term) {
  background-color: #fff2a8;
  color: #222;
}

JavaScript:

const paragraph = document.getElementById("custom-highlight-example");
const textNode = paragraph.firstChild;
const start = textNode.textContent.indexOf("CSS");
if (start !== -1 && "highlights" in CSS && "Highlight" in window) {
  const range = document.createRange();
  range.setStart(textNode, start);
  range.setEnd(textNode, start + 3);
  CSS.highlights.set("css-term", new Highlight(range));
}
Browser Result

Learning CSS makes web design easier and more flexible.

In supporting browsers, the word "CSS" appears with a light yellow background.

The remaining paragraph text retains its normal appearance.

The JavaScript creates a range, registers a named highlight, and leaves the original HTML unchanged.

Note: This example requires support for the CSS Custom Highlight API. If the API is unavailable, the paragraph remains readable without custom highlighting.

Highlighting Multiple Ranges

A single Highlight object can contain multiple text ranges.

This is useful for highlighting every occurrence of a search term.

For example:

<p id="multiple-example">CSS controls colors. CSS also controls layouts.</p>

The following JavaScript finds both occurrences of "CSS":

const paragraph = document.getElementById("multiple-example");
const textNode = paragraph.firstChild;
const text = textNode.textContent;
const ranges = [];
let position = 0;
while ((position = text.indexOf("CSS", position)) !== -1) {
  const range = document.createRange();
  range.setStart(textNode, position);
  range.setEnd(textNode, position + 3);
  ranges.push(range);
  position += 3;
}
if ("highlights" in CSS && "Highlight" in window) {
  CSS.highlights.set("all-css", new Highlight(...ranges));
}

The indexOf() method searches for each occurrence of the word.

A new range is created for every match.

The spread syntax ...ranges passes all matching ranges to the Highlight constructor.

The registered ranges can share one CSS rule:

::highlight(all-css) {
  background-color: #fff2a8;
}

Both occurrences receive the same highlight styling in supporting browsers.

This technique can be extended to search results, document annotations, and other text-highlighting features.

Removing Highlights

Custom highlights can be removed from the registry using JavaScript.

To remove a specific named highlight:

CSS.highlights.delete("search-result");

This removes the registered highlight named search-result.

To remove all custom highlights:

CSS.highlights.clear();

The clear() method removes every entry from the document's custom highlight registry.

Removing a highlight does not delete or modify the original text.

The CSS rule can remain in the stylesheet, but it has no matching registered ranges until a highlight with that name is registered again.

For applications with several independent highlighting features, use delete() to avoid removing highlights owned by other features.

::highlight() vs. ::selection

The ::highlight() and ::selection pseudo-elements both style text ranges, but they serve different purposes.

::highlight()

The ::highlight() pseudo-element styles text ranges registered through the CSS Custom Highlight API.

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

These highlights are controlled programmatically and can remain visible without user text selection.

::selection

The ::selection pseudo-element styles text selected by the user.

::selection {
  background-color: #0066cc;
  color: #fff;
}

The selected text receives a blue background and white text while the selection is active.

Unlike ::highlight(), ::selection does not require registering a Highlight object.

The two pseudo-elements can be used together, although overlapping highlights follow the browser's highlight painting and priority rules.

Supported CSS Properties

The ::highlight() pseudo-element supports a restricted collection of CSS properties.

Common supported properties include:

Property Purpose
color Changes the highlighted text color.
background-color Changes the highlight background color.
text-decoration-line Controls underline and other text decoration lines.
text-decoration-color Changes the text decoration color.
text-decoration-style Controls the text decoration pattern.
text-shadow Adds shadow effects to highlighted text.
text-emphasis-color Controls the color of text emphasis marks.

Properties such as display, padding, margin, border, and font-size do not apply to custom highlight pseudo-elements.

The restricted styling model prevents highlights from changing the document's layout.

For example, the following rule should not be used to add padding around highlighted text:

::highlight(search-result) {
  padding: 10px;
}

Use supported color and text decoration properties instead.

Limitations

The ::highlight() pseudo-element has several important limitations.

  • It requires text ranges to be registered through JavaScript.
  • It does not automatically search for words or phrases.
  • It supports only a restricted collection of CSS properties.
  • It cannot add padding, borders, or other box-model styling around highlighted text.
  • It does not create new HTML elements or modify the document's text.
  • It does not automatically update search results when the document's text changes.
  • Overlapping highlights can have different painting priorities.
  • Older browsers may not support the CSS Custom Highlight API.

For example, the following CSS does not highlight every occurrence of the word "CSS" by itself:

::highlight(css-term) {
  background-color: yellow;
}

A matching highlight must first be registered using JavaScript.

The application is responsible for finding text matches, maintaining ranges, and updating highlights when necessary.

Accessibility Considerations

Custom highlights can improve the visibility of search results and annotations, but visual highlighting alone may not communicate enough information to every user.

Follow these accessibility practices:

  • Maintain sufficient contrast between highlighted text and its background.
  • Do not rely on color alone to communicate important information.
  • Provide text descriptions or other indicators when highlights have specific meanings.
  • Keep the original text readable when the Custom Highlight API is unavailable.
  • Ensure keyboard users can access any controls used to manage highlights.
  • Do not assume that custom highlights are announced by screen readers.
  • Avoid excessive highlighting that makes text difficult to read.

The CSS Custom Highlight API provides visual styling but does not automatically add semantic meaning to the highlighted text.

For applications that need to communicate annotations or search results to assistive technology, provide accessible labels, status messages, or other appropriate interface elements.

Because custom highlights do not alter the original text, the document remains readable when highlight styling is unavailable.

Browser Support

The ::highlight() pseudo-element and CSS Custom Highlight API are available in current versions of major modern browsers, including Chrome, Edge, Firefox, and Safari.

Older browser versions may not support the API or may have differences in highlight rendering.

Developers can check for support before registering highlights:

if ("highlights" in CSS && "Highlight" in window) {
  // Register custom highlights.
}

This check helps prevent errors in browsers that do not provide the required interfaces.

For current compatibility information, visit Can I Use? .

Also consult the MDN documentation for the CSS Custom Highlight API.

Specifications

The ::highlight() pseudo-element is defined in the CSS Custom Highlight API Module Level 1 .

The styling behavior of highlight pseudo-elements is also described in the CSS Pseudo-Elements Module Level 4 .

These specifications describe how custom highlights are registered, styled, and painted within a document.