Simple Static site/blog search in 14 Lines of JavaScript
Tags: javascript, blogging, search
Published: 2021-04-11 10:11:08

---
title: "Simple Static site/blog search in 14 Lines of JavaScript"
tags:
  - javascript
  - blogging
  - search
cover_image: https://images.unsplash.com/photo-1586769852836-bc069f19e1b6?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80
published: true
canonical_url: https://cri.dev/posts/2021-04-06-simple-static-site-blog-search-javascript-client/
---

**Originally posted on [cri.dev](https://cri.dev/posts/2021-04-06-simple-static-site-blog-search-javascript-client/)**

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

I am currently using this under [/posts](https://cri.dev/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](https://github.com/christian-fei/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](https://github.com/christian-fei/devblog), and settled with [Eleventy](https://www.11ty.dev/)

## How it works

Under [/posts](https://cri.dev/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:

```html
<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-item`s `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:

```js
;(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:

```html
<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](https://codepen.io/christian-fei/pen/abpyERy) if you need to better understand how to structure your markup.

**Originally posted on [cri.dev](https://cri.dev/posts/2021-04-06-simple-static-site-blog-search-javascript-client/)**