Quickstart: Customizing the search UI with Search.js
Introduction
While the Search.js library provides a modern and responsive user interface out of the box with its "boo" theme, you will often want to tailor the look and feel to perfectly match your website's branding and layout. This guide covers how to override the default HTML templates used by Search.js. By providing your own templates, you gain full control over the structure and styling of every part of the search experience, from the overall layout to the individual product tiles and filters.
What you'll learn
- How the Search.js templating system works.
- How to override the main search layout to rearrange components.
- How to customize the template for a single search result to match your site's product listings.
- How to change the appearance of facet filters.
Who is this guide for
- Developers using Search.js who want to create a custom-branded and uniquely styled search experience.
Prerequisites
- You should have a working Search.js implementation, as covered in the "Quickstart: Implementing a Search Results Page with Search.js" guide.
- Basic knowledge of HTML and CSS.
Step-by-step
Step 1: Understand how templating works
Search.js
uses a simple templating system. To customize it, you need to follow two rules:
-
Define templates in
<script>
tags: Each custom template must be placed inside its own<script type="text/x-template">
tag. This tag needs a specific id attribute that tellsSearch.js
which component it corresponds to (e.g.,id="template-search"
for the main layout). -
Load templates first: You must place your custom template
<script>
tags in your HTML before the script that loadssearch.js
. This ensures your custom HTML is ready when the library initializes.
If you don't provide a custom template for a component, the library will simply use its default built-in version.
Step 2: Customize the main layout (template-search
)
This is the main template that controls the overall structure of your search page. Think of it as the main container for all other UI components. By editing this template, you can define the high-level layout, such as creating a two-column design with filters on the side and results in the main area.
Key components to place:
-
<facets>
: The container where all your filter controls (brand, category, etc.) will be rendered. -
<results>
: The container where the grid of individual search result tiles will appear. -
<pagination>
: The component that handles page navigation. -
<sort>
: The dropdown menu that allows users to change the sort order.
Example: Move filters to the right
To move the filter facets from the default left side to the right, you can simply change their order in your HTML structure.
<script type="text/x-template" id="template-search">
<div class="search-layout lb-search">
<!-- Main content column -->
<div class="search-main-content">
<h1>Search results for "{{ query }}"</h1>
<sort></sort>
<results></results>
<pagination></pagination>
</div>
<!-- Right-side column for facets -->
<div class="search-sidebar">
<facets></facets>
</div>
</div>
</script>
Step 3: Customize the search result tile (template-result-default
)
This is the most common and impactful customization. This template defines the HTML for a single item in the search results list. You have access to all of your product's indexed data inside the result object, allowing you to display any attribute you need, such as title, image, brand, and price.
Example: Create a custom product card
<script type="text/x-template" id="template-result-default">
<div class="my-product-card">
<a :href="result.url">
<img :src="result.attributes.image_link" :alt="result.attributes.title" class="my-product-image">
<div class="my-product-info">
<h3 class="my-product-title" v-html="result.attributes.title"></h3>
<p class="my-product-brand">{{ result.attributes.brand }}</p>
<div class="my-product-price">{{ result.attributes.price_amount | price }}</div>
</div>
</a>
</div>
</script>
Key Tip: Use v-html="result.attributes.title"
to ensure that search term highlights (like <em>
tags) are rendered correctly.
Step 4: Customize facet filter templates (template-facet-multichoice)
Finally, you can restyle the filters themselves. Each filter type has its own template. The most common one is template-facet-multichoice, which is used for text-based filters where users can select one or more options (e.g., brand, color).
This template receives the name of the facet (e.g., "brand") and an array of values. Each value object contains the option's name, the number of matching hits (hits_count
), and a used flag to indicate if it's currently selected.
Example: Change checkboxes to buttons
If you want to display your brand filters as styled buttons instead of a list of checkboxes, you can override the multichoice facet template.
<script type="text/x-template" id="template-facet-multichoice">
<div class="my-facet">
<h3>{{ name }}</h3>
<div class="my-facet-options">
<!-- Loop through each available filter option -->
<div v-for="val in values">
<label
class="my-facet-button"
:class="{ 'active': val.used }"
>
<input v-model="val.used" type="checkbox" style="display:none;">
{{ val.value }} ({{ val.hits_count }})
</label>
</div>
</div>
</div>
</script>
This example replaces the default list with custom-styled <label>
elements that act as buttons, while keeping the underlying functionality intact.
Best Practices
-
Start with the 'boo' theme: Even when using custom templates, it's a good idea to keep
Theme: 'boo'
in your configuration. The theme provides a solid foundation of default styles for components you don't override, ensuring a consistent look. - Keep it simple: Only override the templates you need to change. If the default pagination or sorting component works for your design, there's no need to create a custom version.
Next Steps
With full control over your search UI, you can now focus on the underlying logic and data: