about

blog

CSS filter posts by category

As I also plan to upload non-technical posts and notes on my website, I added the ability to filter content based on categories. Trying to avoid another Javascript solution, I remembered the CSS :has selector (which I read about in a blog post from Ryan Mulligan’s website).

I based my solution on his examples, tailoring it to the classes available in my Hugo theme. First, I added a partial with a fieldset and included it in the HTML template used for lists. For now, the categories are hard-coded, as I don’t plan on adding more in the future:

<fieldset>
<legend>Filter by category:</legend>
 
<div>
<input type="radio" id="all" name="filter" value="all" checked />
<label for="all">Show all</label>
</div>
 
<div>
<input type="radio" id="tech" name="filter" value="tech" />
<label for="tech">Only technical</label>
</div>
 
<div>
<input type="radio" id="nontech" name="filter" value="nontech" />
<label for="nontech">Only non-technical</label>
</div>
</fieldset>

Next, I added the following to my css:

fieldset {
opacity: 75%;
font-size: 0.75em;
border: dotted;
border-width: 1px;
}
 
body:has([name="filter"][value="tech"]:checked)
.post-line:not([category="tech"]) {
display: none;
}
 
body:has([name="filter"][value="nontech"]:checked)
.post-line:not([category="nontech"]) {
display: none;
}

Finally, to make the filters work, I added a category to every post or note in Hugo:

---
title: "CSS filter posts by category"
date: "2024-08-24"
category: "tech"
---

and included this category in the partial for post entries:

<div class="post-line" category="{{ .Params.category }}">
</div>