Global site search
One search box across the whole site - every enabled collection and static pages - relevance-ranked. Previously this meant writing custom JavaScript against the search API; now it's attributes, like everything else.
Shared setup - the script tag, keys, and data binding - is in the getting started guide. For a search box over a single CMS list, see keyword search.
Minimal setup
Three things: a wrapper with a key, an input, and at least one template card. The truly minimal version is one div - the results container defaults to the wrapper itself, and only rendered cards are ever cleared from it, so the input and state elements can live right beside them:
<div data-slater-search-list="site">
<input type="text" data-slater-search="site" placeholder="Search…" />
<a data-slater-template data-slater-item-href>
<h3 data-slater-bind-text="name"></h3>
<p data-slater-bind-text="matchedContext"></p>
</a>
</div>| Attribute | On | Value | Required |
|---|---|---|---|
data-slater-search-list | a wrapper (plain div) | the block's key - shares one namespace with list keys, don't reuse one | yes |
data-slater-search | <input> | the key | yes |
data-slater-template | one or more cards inside the results container | (no value) = default card | yes - there is no .w-dyn-item to fall back to. Templates are removed from the DOM at load, so mark placeholder cards freely. |
The usual controls work with the key: data-slater-load-more, data-slater-empty, data-slater-count, data-slater-clear, data-slater-for.
Optional attributes
On the wrapper (config equivalents: window.SlaterSearchConfig.search = { site: { initialLimit, loadMoreAmount, minLength, siteId, endpoint } } - attributes win, as everywhere):
| Attribute | Value | Default |
|---|---|---|
data-slater-results | the key - an explicit items container | the wrapper itself |
data-slater-min-length | integer - min chars before searching | 2 |
data-slater-page-size | integer | 20 |
data-slater-load-more-amount | integer | the page size |
data-slater-site | Webflow site id | <html data-wf-site> |
Elsewhere:
| Attribute | On | Purpose |
|---|---|---|
data-slater-initial | any element, value = the key | Shown only while the block idles (query empty / below min length). |
Behavior
- The block idles until the visitor types at least
min-lengthcharacters; while idle thedata-slater-initialelement is shown and nothing is fetched - the empty element, count and load-more button are hidden/cleared. Clearing the input returns to idle, and a late response from an aborted request never repopulates the list. - Empty vs idle:
data-slater-initialanddata-slater-emptynever show together. Any real response - even zero results - ends the idle state; zero results shows the empty element. A failed request shows neither: nothing was learned about the data, so the block stays as it was. Author both state elements visible - the embed hides them via the inline style (see the note in the getting started guide). - Deep links:
?q=termor?query=termin the page URL runs the search on load and pre-fills the input (qwins when both are present).?query=is what Webflow's native search form submits — and what a typeahead navbar input sends on Enter — so a nav-bar<form action="/search">just works as a site-wide search bar. - Queries are capped at 100 characters — longer input is truncated, not an error.
- Each new query resets load-more pagination to the first page.
- A search block has no server-rendered fallback: if the very first request fails, the container simply stays empty (the idle element remains).
What you can bind
Results are normalized to the same shape as list items - every CMS field works with data-slater-bind-* - plus three reserved fields:
| Field | Value |
|---|---|
url | A ready link: the page's published path, or /<collection-slug>/<slug> for a CMS item |
collection | The result's collection slug, or the literal page for a static page |
matchedContext | A text snippet around the match, for display |
data-slater-item-href (no value - it uses url) or data-slater-bind-href="url". Don't write data-slater-href="{url}" — patterns percent-encode their placeholders, which mangles the slashes.Different cards per collection
Give data-slater-template a value to use a different card (and link pattern) per collection; the value page is reserved for static pages. The valueless template is the default for everything else:
<div data-slater-results="site">
<a data-slater-template data-slater-item-href> …generic card… </a>
<a data-slater-template="blog" data-slater-href="/blog/{slug}"> …blog card… </a>
<a data-slater-template="page" data-slater-item-href> …page card… </a>
</div>Limits
- No filters, sorting, facets, or locale yet - results come relevance-ranked.
data-slater-filter/data-slater-sortcontrols pointed at a search block are ignored with a console warning. Need a filterable cross-collection list? That's exactly what a multi-collection list is. - The ranked window is the top 1000 results; load-more stops there.
data-slater-expanddoes work here - it expands references across every collection in the results. See Fields from a linked collection.data-slater-search-fieldsdoes not - a site-wide search spans collections that share no field schema. Setting it here logs a warning and is ignored; scope a per-collection list instead.
Future: data-slater-search-mode="ai" (wrapper) and data-slater-overview (element) are reserved for the AI-powered variant - don't use these attribute names for anything else.