A good first building block

Search text inside a page

Highlight matches in an article and move through results without searching navigation or controls.

HTMLCSSJavaScriptNo dependencies
Edit in playground

Live preview

Explore the result below

HTML

<main><h1>Find a little idea</h1><form id="search-form"><label for="search-term">Search this article</label><input id="search-term" type="search" maxlength="80"/><button id="search-submit" type="button">Find</button></form><p id="search-status" role="status">Enter a word to search the article.</p><div class="search-controls"><button id="previous" disabled>Previous</button><button id="next" disabled>Next</button></div><article id="search-content"><h2>Small ideas, useful code</h2><p>HTML gives your idea a structure. A little CSS makes the structure easier to read.</p><p>A little JavaScript turns a static idea into something you can try. Begin with a small example, change it and see what happens.</p><p>Keep your code simple. Make the next useful idea clear to the person using it.</p></article></main>
Read the complete HTML document
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<title>My code example</title>
<style>
:root{font-family:system-ui,sans-serif;color:#18223b}*{box-sizing:border-box}body{margin:0;min-height:100vh;padding:24px;background:#edf1ff;display:grid;place-items:center}main{width:min(100%,480px);background:white;border-radius:20px;padding:24px}h1{font-size:24px;margin:0 0 16px}button,input{font:inherit}button{min-height:44px;border:1px solid #afbddd;border-radius:10px;padding:10px 14px;background:#eff3ff;color:#18223b;cursor:pointer}button:focus-visible,input:focus-visible{outline:3px solid #3658bf;outline-offset:3px}p{line-height:1.65}button:disabled{opacity:.5;cursor:default}form{display:flex;flex-wrap:wrap;gap:8px}label{width:100%}input{min-width:0;flex:1;border:1px solid #afbddd;border-radius:8px;padding:10px;width:100%}mark{background:#ffe79a;color:#18223b}mark.current{outline:2px solid #3658bf;outline-offset:2px}.search-controls{display:flex;gap:8px}
</style>
</head>
<body>
<main><h1>Find a little idea</h1><form id="search-form"><label for="search-term">Search this article</label><input id="search-term" type="search" maxlength="80"/><button id="search-submit" type="button">Find</button></form><p id="search-status" role="status">Enter a word to search the article.</p><div class="search-controls"><button id="previous" disabled>Previous</button><button id="next" disabled>Next</button></div><article id="search-content"><h2>Small ideas, useful code</h2><p>HTML gives your idea a structure. A little CSS makes the structure easier to read.</p><p>A little JavaScript turns a static idea into something you can try. Begin with a small example, change it and see what happens.</p><p>Keep your code simple. Make the next useful idea clear to the person using it.</p></article></main>
<script>
const content=document.querySelector("#search-content"),status=document.querySelector("#search-status"),previous=document.querySelector("#previous"),next=document.querySelector("#next");let matches=[],current=-1;
function show(index){if(!matches.length)return;current=(index+matches.length)%matches.length;matches.forEach((m,i)=>m.classList.toggle("current",i===current));matches[current].focus();matches[current].scrollIntoView({block:"nearest"});status.textContent="Match "+(current+1)+" of "+matches.length+".";}
function search(){content.querySelectorAll("mark").forEach(m=>m.replaceWith(document.createTextNode(m.textContent)));content.normalize();matches=[];current=-1;const term=document.querySelector("#search-term").value.trim().toLocaleLowerCase();if(term){const walker=document.createTreeWalker(content,NodeFilter.SHOW_TEXT),nodes=[];while(walker.nextNode())nodes.push(walker.currentNode);for(const node of nodes){const raw=node.textContent,lower=raw.toLocaleLowerCase();let position=0,index=lower.indexOf(term),fragment=document.createDocumentFragment();if(index<0)continue;while(index>=0){fragment.append(document.createTextNode(raw.slice(position,index)));const mark=document.createElement("mark");mark.tabIndex=-1;mark.textContent=raw.slice(index,index+term.length);fragment.append(mark);matches.push(mark);position=index+term.length;index=lower.indexOf(term,position);}fragment.append(document.createTextNode(raw.slice(position)));node.replaceWith(fragment);}}previous.disabled=next.disabled=matches.length===0;status.textContent=matches.length?matches.length+" matches. Use Next or Previous.":term?"No matches.":"Enter a word to search the article.";}
document.querySelector("#search-submit").addEventListener("click",search);document.querySelector("#search-term").addEventListener("keydown",e=>{if(e.key==="Enter"){e.preventDefault();search();}});
next.addEventListener("click",()=>show(current+1));previous.addEventListener("click",()=>show(current-1));
</script>
</body>
</html>

A little guide to making it yours

  1. Copy the code and save it in a file named example.html.
  2. Open the file in your browser to see the complete example.
  3. Change the text and structure in the HTML.
  4. Adjust the colors and spacing in the CSS, or experiment in the playground.

How it works

Only text nodes inside the article are searched. The script creates mark elements with textContent, removes previous marks before searching again, and never injects the query as HTML. Search is case-insensitive and matches literal text within individual text nodes; it does not search across markup boundaries or implement language-aware Unicode normalization.

Historical purpose: The stage-one 2014 archive recovery verified this exact detail purpose. This is an original modern implementation; no archived third-party code, credit link, remote script or guessed numeric preview mapping is reused.

Troubleshooting and limits

Search matches literal text inside the sample article only. Words split by nested markup do not match across nodes. Use Next or Previous after finding results. This is not a site-wide or server search, and it never injects the query as HTML.

This is newly authored code. It uses system fonts and no external assets.

Keep the ideas going