cri.dev
about posts rss

Simple Static site/blog search in 14 Lines of JavaScript

Published on
Tagged with search4 static4 site3

This is my approach to a purely client side search feature for static blogs and sites.

I am currently using this under /posts to let readers search through my blog posts.

Read more below about how to integrate it in your site.

Backstory

In 2015 I did a similar thing for Jekyll sites, namely Simple-Jekyll-Search

It’s gotten quite a bit of attention and merged various Pull-Requests (64!) from others.

I ditched Jekyll a few years ago, to use a JavaScript based static site generator:

My home-made static site generator devblog, and settled with Eleventy

How it works

Under /posts I render the full list of blog posts.

(Not with the full content but with an excerpt/description.)

In my Nunjucks template I render the posts like this:

<div class="searchable">
  <input type="text" autofocus placeholder="πŸ” Search posts"/>
  {% set postslist = collections.post | reverse %}
  {% for post in postslist %}
    <div class="searchable-item" data-search="{{ post.data.title | escape }} {{ post.data.tags | json | escape }}">
    ...
    </div>
  {% endfor %}
</div>

The idea is the following:

Within a .searchable element

  • look for a input element and attach an event listener to it (keyup event)
  • when searching, parse all .searchable-items data-search attribute and test a RegExp on it
  • make items that match visible, and make others disappear

Code

This is the full code for the search functionality on this blog:

;(function search () {
  ;[...document.querySelectorAll('.searchable')].forEach(makeSearchable)
  function makeSearchable ($searchable) {
    const $searchableItems = [...$searchable.querySelectorAll('.searchable-item')]
    const $search = $searchable.querySelector('input')
    $search.addEventListener('keyup', (e) => {
      $searchableItems.forEach(function ($el) {
        const text = $el.getAttribute('data-search') || $el.innerText
        const show = new RegExp(e.target.value, 'i').test(text)
        $el.style.display = show ? '' : 'none'
      })
    })
  }
})()

How to integrate it on your site

Grabbed the JavaScript above and put it in a <script> tag.

Define a minimal markup to enable the search functionality:

<div class="searchable">
  <input type="text" autofocus placeholder="πŸ” Search posts"/>
  <!-- Loop through your blog posts -->
  <div class="searchable-item">
  ...
  </div>
</div>

Make sure you have the wrapper element .searchable, containing an input field and your post items with the .searchable-item class.

By default the search function will match the blog posts to filter with the element’s innerText.

Optionally, apply a data-search attribute to each .searchable-item and set the value of your blog post title, tags, short description etc.

Full example

Check out a full example on CodePen if you need to better understand how to structure your markup.

Here is how it looks

JavaScript search

some description

Another JavaScript library

some other description

Design resources

description about design resources

Other topic

some other topic description

Here, have a slice of pizza πŸ•