What We’re Working Towards
Each instructor here at Tuts+ has his or her own archive page. We’re going to recreate a tutorial list like this, using our own markup. Then, we’ll implement a component that will filter the posts based on the categories they belong to.
Here’s our final project:
Let’s get building!
1. Begin With the HTML Markup
We start by identifying the filter categories in our component. In this example, we’ll use seven filters:
To do this we first define seven radio buttons which we group under the categories keyword. By default, the first radio button is checked:
Next we set up another ordered list which includes the elements we want to filter (our cards). Each of the filtered elements will have a custom data-category attribute whose value is a whitespace-separated list of filters:
<!-- 10 more list items here -->
In our case, the filtered elements will be posts. So the markup we’ll use to describe a post along with its meta (title, image, categories) looks like this:
Note: For readability reasons, in our CSS we don’t group common CSS rules.
Adding the Filtering Styles
The idea here is surprisingly simple. Each time we click on a filter, only the corresponding filtered elements (posts) should appear. To implement that functionality, we’ll use a combination of the following CSS goodies:
The first bit [value="CSS"]:checked looks for checked radio buttons with a specific value (“CSS” in this case).
After that, the tilde (~) is what we nowadays call the “subsequent sibling selector”. It selects elements which have the same parent as the preceding element, even if they don’t immediately follow in the markup. So ~ .posts .post looks for the element .posts .post which shares the same parent as the checked radio input.
To get more specific still, :not([data-category~="CSS"]) refines our selector to only those .post elements which do not have a data-category attribute which contains a value of CSS somewhere within a space-separated list.
It then applies a display: none; to any elements which match those criteria.
It’s quite a complex selector, even though it’s perfectly logical. In human language terms you might describe it as:
“When the radio with a value of ‘CSS’ is checked, find any subsequent sibling elements which do not contain “CSS” in their data-category list, and hide them.”
Last Bit of Styling
As a last step, we add a rule which highlights the active filter category:
This filtering is nicely accessible by default; we can filter our items with the keyboard keys. First press the Tab key to move focus to the checked radio button. Next press the Arrow keys to move focus and selection to the other radio buttons. Try it yourself:
That’s it folks! With just a few CSS rules and some structured markup, we managed to build a fully functional filtering component.
I hope you enjoyed this exercise and that it has helped you expand your understanding of CSS selectors. As always, thanks for reading!