Marking text without touching the DOM
Live demo
A range registered with the browser, painted where it falls, and removed again without a single element being wrapped, rebuilt or re-rendered.
Caveat and fallback
CaveatA custom highlight accepts a short list of properties and nothing else: color, background-color, the text decoration set and text-shadow. No padding, no border, no radius. The ranges are yours to maintain too, so any edit to the text leaves them pointing at the wrong offsets, and because nothing in the DOM changed a screen reader learns nothing from the marking.
FallbackTest for CSS.highlights before you build a single range; where it is missing the paragraph simply never lights up, which is the right way to lose a search affordance. Wrapping matches in <mark> still works and is still the better answer when the marking is part of the content rather than a passing state of the interface.
Source code
<p>a range painted where it falls</p>
::highlight(hits) {
background-color: #6fa8dc6b;
color: #e6eaf2;
}
// no wrapper elements, no reflow
const r = new Range();
r.setStart(node, 2); r.setEnd(node, 7);
CSS.highlights.set('hits', new Highlight(r));
Published
Questions
How do I highlight search results without wrapping them in span elements?
Build a Range for each match and register them with CSS.highlights.set('hits', new Highlight(...ranges)), then style ::highlight(hits). Nothing in the document changes, so there is no reflow and no wrapper to unpick afterwards.
Why can I not give a custom highlight a border or padding?
A highlight pseudo-element paints over existing text rather than creating a box, so only color, background-color, the text decoration properties and text-shadow apply. Anything that would change layout is ignored by design, which is also why highlighting cannot make the text move.
Do screen readers announce a custom highlight?
No. The DOM is untouched, so assistive technology has nothing new to read. Use it for transient interface state such as a live search, and keep real markup like <mark> for emphasis that is part of the content.