Originally posted on cri.dev
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-item
sdata-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.
Originally posted on cri.dev
Top comments (0)