StaticSearch web component
(updated )
1,030 words, 6-minute read
The <static-search> web component provides full search functionality in any web page using HTML alone. It’s the easiest option, e.g.
HTML excerpt
<!-- include script once on your page -->
<script type="module" src="/search/staticsearch-component.js"></script>
<!-- define web component -->
<static-search title="press Ctrl+K to search">
<p>search</p>
</static-search>
The component uses a Shadow DOM so your page styles do not affect its layout. You can safely style it using custom properties or ::part selectors.
Search activation element #
Place <static-search> anywhere you want a search icon or text – perhaps in the page <header>. It requires a single inner element that the user clicks to activate the search. This opens a modal dialog with an input field and results list.
The activation element must be an element with content – it cannot be empty or text only. You can also assign part attributes for styling, e.g.
HTML excerpt
<static-search title="press Ctrl+K to search">
<a part="staticsearchactivate" href="https://duckduckgo.com/?q=search%20site:mysite.com">
<svg part="staticsearchicon" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24">
<path d="M10 4a6 6 0 1 0 0 12 6 6 0 0 0 0-12Zm-8 6a8 8 0 1 1 14.3 5l5.4 5.3a1 1 0 0 1-1.4 1.4l-5.4-5.4A8 8 0 0 1 2 10Z"></path>
</svg>
</a>
</static-search>
Web component attributes #
Add any of the following <static-search> attributes to control functionality:
| attribute | description |
|---|---|
title="<string>" | activation instructions (users can click or press Ctrl|Cmd+K) |
label="<string>" | the label on the search <input> |
minfound="<num>" | only show pages containing at least this proportion of search words (0.0 to 1.0) |
minscore="<num>" | only show pages with total relevancy scores of this or above on results |
maxresults="<num>" | show up to this number of pages on the results |
highlight="<any>" | scroll to and highlight the first matching search terms |
Search results provide a found value indicating the percentage of search words found on a page, e.g. two of four search words is 0.5.
setting
minfound="0"(the default) is a logical OR. A page appears in results when it contains ANY of the search words.setting
minfound="1"is a logical AND. A page appears in results when it contains ALL the search words.setting
minfound="0.5"means a page appears in results when it contains at least half of the search words.
Pages still appear in order of relevancy, but higher minfound values will reduce the number of results.
Set a highlight attribute to scroll to and highlight the first matching search terms on a results page. This uses text fragment links which can have issues:
searching for “highlight” will return pages containing “highlighted” and “highlighter”, but they are not highlighted.
A highlighted word could appear outside your main content, such as in a menu.
Overriding HTML templates #
You can change the HTML shown when displaying results using <template> elements.
Search results message #
When search results are available, you’ll see a message such as:
7 found for “web component”…
It uses the HTML code:
HTML excerpt
<p part="resultmessage">
<span part="resultcount"></span> found for
<span part="searchterm"></span>…
</p>
You can override this using a <template> with an ID of staticsearch_resultmessage in your HTML page (it can be within <static-search> or elsewhere). You must set the part attributes "resultmessage", "resultcount", and "searchterm" as necessary, e.g.
HTML excerpt
<template id="staticsearch_resultmessage">
<p part="resultmessage">
StaticSearch found
<span part="resultcount"></span> results
for <span part="searchterm"></span>:
</p>
</template>
Search result item #
An ordered list (<ol part="searchresult">) contains search results. Each page result uses the HTML:
HTML excerpt
<li part="item">
<a part="link">
<h2 part="title"></h2>
<p part="meta">
<time part="date"></time> –
<span part="words">0</span> words
</p>
<p part="description"></p>
</a>
</li>
You can override this using a <template> with an ID of staticsearch_item in your HTML page (it can be within <static-search> or elsewhere). Set the part attributes "item", "link", "title", "meta", "date", "words", and "description" as necessary, e.g. show the title but no description, date, or word count in an <article>:
HTML excerpt
<template id="staticsearch_item">
<li part="item">
<article>
<h2 part="title"><a part="link"></a></h2>
</article>
</li>
</template>
CSS custom property styling #
You can style <static-search> elements using CSS custom properties (variables) in the :root or any ancestor element. StaticSearch uses a neutral set of colors and follows your site’s light/dark theme if your CSS sets color-scheme: light dark;, color-scheme: light;, or color-scheme: dark; as necessary.
The following code shows custom property defaults you can change:
CSS excerpt
:root {
/* font size */
--staticsearch-fontsize: 1em;
/* modal dimensions */
--staticsearch-maxwidth: 60ch;
--staticsearch-margin: 3vmin;
--staticsearch-padding: 2vmin;
--staticsearch-fieldset-height: calc(3em + (2 * var(--staticsearch-padding)));
/* colors */
--staticsearch-color-back: Canvas;
--staticsearch-color-border: ButtonFace;
--staticsearch-color-fore0: CanvasText;
--staticsearch-color-fore1: color-mix(in oklab, CanvasText 80%, Canvas);
--staticsearch-color-fore2: color-mix(in oklab, CanvasText 60%, Canvas);
--staticsearch-color-link: color-mix(in oklab, LinkText 70%, CanvasText);
--staticsearch-color-visited: color-mix(in oklab, VisitedText 70%, CanvasText);
--staticsearch-color-shadow: #000;
--staticsearch-color-backdrop: color-mix(in srgb, var(--colshad0), transparent 30%);
--staticsearch-backdrop-blur: 3px;
}
CSS ::part selector styling #
You can target static-search elements using ::part selectors. StaticSearch generates HTML such as this – note the part attribute names:
HTML excerpt
<static-search>
<!-- user-defined activation element -->
<p>search</p>
<!-- dialog with aria-expanded when open -->
<dialog part="dialog" aria-expanded="true">
<!-- close button -->
<form method="dialog">
<button part="close">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path xmlns="http://www.w3.org/2000/svg" fill="currentColor" d="M5.3 5.3a1 1 0 0 1 1.4 0l5.3 5.3 5.3-5.3a1 1 0 1 1 1.4 1.4L13.4 12l5.3 5.3a1 1 0 0 1-1.4 1.4L12 13.4l-5.3 5.3a1 1 0 0 1-1.4-1.4l5.3-5.3-5.3-5.3a1 1 0 0 1 0-1.4Z"/></svg>
</button>
</form>
<!-- search form -->
<search part="search">
<label for="search" part="searchlabel">search</label>
<input type="search" id="search" name="q" minlength="2" maxlength="300" part="searchinput" />
</search>
<!-- search results -->
<div part="results">
<!-- default results message -->
<p part="resultmessage">
<span part="resultcount">1</span> found for
<span part="searchterm">"web component"</span>…
</p>
<!-- results list -->
<ol part="searchresult">
<!-- default results item -->
<li part="item">
<a part="link">
<h2 part="title"></h2>
<p part="meta">
<time part="date"></time> –
<span part="words">0</span> words
</p>
<p part="description"></p>
</a>
</li>
</ol>
</div>
</dialog>
<static-search>
You can target any element with its ::part selector:
CSS excerpt
static-search {
/* modal dialog */
&::part(dialog) {
border: 5px solid #f00;
}
/* input */
&::part(searchlabel) {
text-transform: uppercase;
}
&::part(searchinput) {
font-family: monospace;
}
&::part(resultmessage) {
font-size: 1.5em;
}
&::part(description) {
font-size: 0.8em;
}
}
Re-run the indexer #
Once you have added StaticSearch functionality to your static site’s templates, you should re-run the indexer to ensure word indexes are up-to-date.