← Hub · Open the micro-demo

Search highlighting (find-in-page): <mark>, counts, and next/prev matches

Search highlighting is deceptively easy to get wrong: it often relies on color-only cues, wipes the DOM on every keystroke, or steals focus when you navigate matches.

Live demo: search-highlighting-demo.html (BEFORE/AFTER)

Common failure modes

Minimum viable pattern

One small detail that matters: a “current match” marker

When there are many matches, users need a distinct marker for the current one (e.g., thicker outline + different background). Pair it with status text like “Current: 3 of 12”.

Pseudo-code sketch

// Given a list of paragraphs (strings), rebuild DOM safely.
// 1) escape user term for regex
// 2) split text into [before, match, after] pieces
// 3) append text nodes + <mark> nodes
// 4) announce counts with role=status (polite)

function render(term){
  container.textContent = '';
  marks = [];
  for (p of paragraphs){
    el = document.createElement('p');
    appendWithMarks(el, p, regex(term));
    container.appendChild(el);
  }
  status.textContent = `${marks.length} matches for “${term}”`;
}

Tip: handle empty matches defensively (avoid regex loops on zero-length matches).