Building a custom word highlighter in JavaScript can be achieved using two completely different strategies: the traditional DOM Manipulation method or the modern, performance-optimized CSS Custom Highlight API.
The approach you choose dictates how your code interacts with the underlying browser page: Feature / Detail Traditional DOM Modification Modern CSS Custom Highlight API Performance Slow (Triggers full page re-layouts/re-paints) Extremely fast (No structural changes to DOM) DOM Pollution Messy (Injects explicit tags) Clean (Leaves raw text completely unmodified) Complex Text Care Hard (Breaks if word splits across nested HTML elements) Easy (Can map text ranges seamlessly) Browser Compatibility Universal (Works on any browser) High (Fully standard across modern browsers) Option 1: The Modern CSS Custom Highlight API (Recommended)
This strategy tracks text indices to form Range boundaries. It then maps those boundaries to a CSS style layer without wrapping text in HTML tags. 1. Define the Highlighting Theme in CSS
Use the ::highlight() pseudo-element to hook your custom highlight key to a style sheet:
/“word-picker” matches the registration name in JavaScript / ::highlight(word-picker) { background-color: #ffde03; color: #000000; } Use code with caution. 2. Implement the Search Logic in JavaScript
Iterate through text nodes to pinpoint specific strings, register ranges, and hand them off to the browser’s native highlight layer: javascript
function highlightWords(targetWord) { // 1. Clear previous highlights to reset state CSS.highlights.clear(); if (!targetWord) return; const articleBody = document.getElementById(“content-area”); const treeWalker = document.createTreeWalker(articleBody, NodeFilter.SHOW_TEXT); const foundRanges = []; let currentNode; // 2. Scan text chunks across the DOM tree while ((currentNode = treeWalker.nextNode())) { const text = currentNode.textContent; let startIndex = text.toLowerCase().indexOf(targetWord.toLowerCase()); // Loop handles instances where a word repeats inside the same block while (startIndex !== -1) { const markerRange = new Range(); markerRange.setStart(currentNode, startIndex); markerRange.setEnd(currentNode, startIndex + targetWord.length); foundRanges.push(markerRange); startIndex = text.toLowerCase().indexOf(targetWord.toLowerCase(), startIndex + targetWord.length); } } // 3. Register ranges to display the visual overlay const highlightRegistry = new Highlight(…foundRanges); CSS.highlights.set(“word-picker”, highlightRegistry); } Use code with caution. Option 2: The Traditional Element Injection Method
This legacy method parses your text and actively injects or wrapper blocks into the element’s innerHTML string.
⚠️ Warning: Avoid running broad RegExp operations blindly on element properties like innerHTML. Doing so risks breaking the layout by accidentally overwriting live HTML link anchors, image properties, or tag classes. javascript
function legacyHighlight(targetWord) { const container = document.getElementById(“content-area”); const fallbackText = container.textContent; // Read clean text safely if (!targetWord.trim()) { container.innerHTML = fallbackText; return; } // Escape special regex syntax symbols safely const safeWord = targetWord.replace(/[-/^$+?.()|[]{}]/g, ‘\\(&'); const parsingRegex = new RegExp(`(\){safeWord}) Use code with caution. Production Framework Alternatives, 'gi'); // Replace matches with HTML wrapper markers container.innerHTML = fallbackText.replace( parsingRegex,$1` ); }
If your application needs complex structural parsing (like reading custom formatting syntax or dealing with vast document structures), use a specialized engine: Writing a syntax highlighter – Stack Overflow
Leave a Reply