Understanding the CSS Custom Highlight API
The CSS Custom Highlight API is a web standard that provides a programmatic way to target specific ranges of text defined by Range objects, without affecting the underlying DOM structure. This capability extends the concept of existing highlight pseudo-elements like ::selection, ::spelling-error, and ::target-text by allowing developers to create arbitrary text ranges rather than being limited to browser-defined ranges.
Key Components of the API
The CSS Custom Highlight API comprises four interconnected components:
- Range Object: A JavaScript API that represents a fragment of a document that can contain nodes and text content. Range objects are fundamental to scripting interactions with document content.
- Highlight Interface: Represents a collection of Range instances to be styled.
- CSS.highlights Registry: A global registry where Highlight objects are registered under unique string names.
- ::highlight() Pseudo-element: A CSS pseudo-element that selects ranges registered under a specific name.
Why the Traditional <mark> Element Falls Short
Before the CSS Custom Highlight API, developers typically used the HTML <mark> element to highlight text. While this approach works for simple cases, it has significant limitations:
- Requires DOM modification to insert
<mark>elements - Cannot easily highlight text spanning multiple HTML elements
- Can cause layout recalculations affecting performance
- Creates invalid HTML when attempting to span non-nesting elements
The <mark> element works well when highlighting simple, contained text within a single parent element. However, highlighting text that spans multiple elements requires inserting multiple <mark> elements, which doesn't visually represent a continuous highlight. This is one reason why modern web development practices favor APIs that avoid direct DOM manipulation.
For developers working with CSS custom properties, the CSS Custom Highlight API integrates seamlessly by allowing highlight styling through the same CSS variable system you already use.
1// Get the element containing the text to highlight2const introText = document.getElementById('intro');3const firstItem = document.getElementById('item1');4 5// Create a Range object6const range = new Range();7 8// Set the range to span from the beginning of one element to the end of another9range.setStartBefore(introText);10range.setEndAfter(firstItem);Creating and Registering Highlights
After defining your Range objects, you create a Highlight object and register it with the CSS engine.
1// Create a Highlight object with one or more ranges2const highlight = new Highlight(range);3 4// Register the highlight with a unique name5CSS.highlights.set('my-custom-highlight', highlight);1/* Apply styles to the custom highlight */2::highlight(my-custom-highlight) {3 background-color: #ffe066;4 color: #000;5 padding: 2px 0;6}Advanced Highlight Operations
Modifying Highlighted Ranges
One powerful feature is that Highlight objects maintain a live reference to their Range objects. When you modify a Range, the highlight automatically updates:
// Extend the highlight to include a new element
const secondItem = document.getElementById('item2');
range.setEndAfter(secondItem);
// The highlight now automatically includes the new content
Highlighting Multiple Ranges
A single Highlight object can contain multiple non-contiguous ranges:
const range1 = new Range();
range1.setStartBefore(document.getElementById('intro'));
range1.setEndAfter(document.getElementById('item1'));
const range2 = new Range();
const fourthItem = document.getElementById('item4');
range2.setStartBefore(fourthItem);
range2.setEndAfter(fourthItem);
const highlight = new Highlight(range1);
highlight.add(range2);
CSS.highlights.set('my-highlight', highlight);
Removing Highlights
// Remove a specific range from a highlight
highlight.delete(range1);
// Or remove the entire highlight from the registry
CSS.highlights.delete('my-custom-highlight');
// Or clear all ranges from a highlight
highlight.clear();
The following CSS properties can be applied to ::highlight() pseudo-elements:
background-color
Sets the highlight background color
color
Sets the text color within the highlight
text-decoration
Adds underlines or strikethroughs
text-shadow
Adds text shadows (with limitations)
cursor
Changes the cursor when hovering
caret-color
Changes the text caret color
Browser Support and Feature Detection
As of 2025, the CSS Custom Highlight API has broad support across modern browsers:
- Chrome and Edge: Full support
- Safari: Full support
- Firefox: Support enabled in recent versions
Implement feature detection for graceful degradation:
if ('highlights' in CSS) {
// Use the CSS Custom Highlight API
} else {
// Fallback to <mark> element approach
}
Frequently Asked Questions
Conclusion
The CSS Custom Highlight API represents a significant advancement in how web developers can programmatically highlight text. By leveraging JavaScript Range objects, Highlight collections, and CSS pseudo-elements, developers can create rich, interactive highlighting experiences without the performance costs and complexity of DOM manipulation. As browser support continues to grow, this API should become the standard approach for any application requiring programmatic text highlighting--from search interfaces to educational content to document readers.
Our web development services team specializes in implementing modern CSS and JavaScript APIs like the CSS Custom Highlight API to create engaging user experiences. Whether you're building search functionality, interactive tutorials, or document annotation tools, mastering this API will elevate your front-end development capabilities.