Style find-in-page highlights without breaking the browser

Big bold words Find In Page beside an isometric machine stamping glowing highlight bands onto a long sheet of text.

Yes, you can style the browser’s find-in-page highlight now with the CSS ::search-text pseudo-element, and on most client sites I’d barely touch it. The feature is real and support is wide, but the default yellow the browser paints is still hard to beat for recognition.

There’s a full almanac entry on ::search-text over on CSS-Tricks, with the syntax, the property list, and the inheritance rules. I’m building on it from the WordPress side: when I’d ship this at all, and when I’d write a few lines of JavaScript instead.

Browser find-in-page, selection, or your own highlight

Highlighted text on a page comes from three places. ::selection styles what the user selects with a mouse or keyboard, and it has never reliably covered find-in-page matches, because browsers draw those themselves. ::search-text closes that gap: it targets exactly the text the find bar matched, and ::search-text:current picks out the match the user is currently on. The third option, ::highlight(name) from the CSS Custom Highlight API, is entirely yours: JavaScript builds the ranges, registers them in CSS.highlights, and the browser paints them.

What you can change about a match

The supported properties are few: color, background-color, text-shadow, text-decoration with its long tail (thickness, offset, skip-ink, and text-decoration-line limited to underline, line-through, none, spelling-error and grammar-error), plus custom properties. Values inherit down the tree and can be overridden per element, so article::search-text can set a base look and strong::search-text can break from it. :past and :future are reserved, and any other pseudo-class chained onto ::search-text is invalid.

When a client insists on customizing this, the version I ship is decoration only:

::search-text {
  text-decoration: underline;
  text-decoration-color: oklch(65% 0.18 240);
  text-decoration-thickness: 0.22em;
  text-underline-offset: 0.15em;
}

::search-text:current {
  text-decoration-color: oklch(62% 0.22 38);
}

I stick to text-decoration because the default background survives, so nobody has to relearn what a match looks like. If you do recolor, WCAG wants at least 4.5:1 contrast between text and background, and I’d check that in the theme’s light and dark schemes.

When I’d build my own highlight instead

::search-text has no JavaScript hook. You can’t open the find bar from script, count matches, or learn what was searched. That all belongs to the browser. On a docs template, a changelog, or a WooCommerce product page where people dig through a long spec table, I’d build the search myself with the Custom Highlight API and leave Ctrl+F as the fallback:

const root = document.querySelector('.entry-content');
const term = 'refund';
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
const highlight = new Highlight();
let node;

while ((node = walker.nextNode())) {
  const text = node.textContent.toLowerCase();
  let i = text.indexOf(term);
  while (i !== -1) {
    const range = document.createRange();
    range.setStart(node, i);
    range.setEnd(node, i + term.length);
    highlight.add(range);
    i = text.indexOf(term, i + term.length);
  }
}

CSS.highlights.set('site-search', highlight);

Then it’s one rule in the stylesheet, ::highlight(site-search) { background-color: oklch(87% 0.17 90); }, and every occurrence lights up. You get match counts, next and previous buttons, and clearing via CSS.highlights.delete(). The styling limits are the same family of properties as ::search-text, which MDN documents in detail. One caveat that bites on real stores: the browser’s find bar skips anything hidden with display: none, with hidden="until-found" as the Chromium exception, so an accordion full of specs can stay invisible to Ctrl+F no matter what you style.

An in-page search like this is the kind of front-end work I take on, and I’m glad to look at whether it fits your setup.

What I’d pick for which site

  • Marketing sites and blogs: ship nothing. The browser default is what people know, and overriding it mostly risks confusion.
  • Stores and docs pages: at most the text-decoration snippet above, in the theme’s style.css or a small custom stylesheet, and no background recoloring.
  • Sites where finding text is the feature, like internal docs or a code reference: Custom Highlight API with your own input.

And if people reach for Ctrl+F because site search keeps failing them, that’s the cheaper problem to fix first.

Paste the text-decoration block into style.css, open the longest page on the site, hard-refresh, and Ctrl+F a term customers use. If the default reads better, delete the block. Two minutes later you’ll know whether the site needs it.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.

Leave a Comment