this post's header image

Using custom HTML Attributes

Just want to see the result? Head to and click on the search button.

I wanted a meaningful reason for people to visit my "blog" page. It was just a copy of my home page without the excerpt about how I liked good code. I realized a search bar would add a lot to the user experience.

I had only one problem. My entire blog was pre-rendered with 11ty. I wanted a way to grab the tag list without stuffing everything into a JS rendered component. That's when I found custom attributes.

Setting and Getting

Any attribute that starts with "data-" gets saved into the dataset variable for a component. For example:

<p id="element" data-my-variable="value">example</p>

Can be queried like so:

const $el = document.querySelector('#element');
const myValue = $el.dataset.myVariable;

As you can see, the JavaScript can access any attribute with the "data-" prefix from the dataset variable on the node. It automatically translates variable names from kebab-case to camelCase to align with JS standards.

Storing complex types

My next challenge was the limitation on what types you can store in the variable. I had an array of tags that I wanted to store, not a string. Because I am using Liquid templates with 11ty, I was able to insert the array like so:

<div class="card" data-post-tags='{{ post.tag_list }}'></div>

Notice the single quotes so that each double quote in the array is assumed to be part of the string.

Then to access it, I had to parse the array with JSON.parse().

const $card = document.querySelector('.card');
const tags = JSON.parse($card.dataset.postTags);

At that point, the tutorial is more about array methods in JS. I used document.querySelectorAll, filter, and includes to find all of the relevant and not relevant posts based on the search input. It was really easy. I was so grateful to have a way to embed custom tags into html and retrieve them through a simple JS API.

Where to go from here

Go check out the search bar in action:

At this point, none of the JS is minimized, so it's easy to see how everything works in the script tag just above the input. I do store it in a separate JS file, but it is baked into the HTML when you run eleventy.

Want to see the full source code?

Respond to this post and join the conversation on DEV