Skip to content

Instantly share code, notes, and snippets.

@MattMcAdams
Created March 4, 2022 03:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MattMcAdams/41220c816e6e353693a06a9436c0add4 to your computer and use it in GitHub Desktop.
Save MattMcAdams/41220c816e6e353693a06a9436c0add4 to your computer and use it in GitHub Desktop.
Filter items by tag with JS
body { font-family: sans-serif; max-width: 1300px; margin: 5rem auto; padding: 0 1rem; }
h1, h2, h3, ul, p { margin: 0 0 1rem 0; }
[hidden] { display: none !important; }
.item-list {
margin: 2.5rem 0;
padding: 0;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15em, 1fr));
grid-gap: 1rem;
}
.card {
list-style: none;
margin: 0;
padding: 1rem;
background: #f7f9fb;
border: 1px solid #d7dce0;
}
.tags {
margin: 0;
padding: 0;
display: flex;
gap: 1rem;
}
.tags li {
padding: 0.5rem 1rem;
background: #d7dce0;
list-style: none;
}
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none; /* hides the native UI */
width: calc(25% - 1rem);
border: 1px solid #d7dce0;
background: white;
padding: 0.5rem 2rem 0.5rem 1rem;
display: block;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8" fill="none" stroke="black"><path d="M7.5 3L4 6 .5 3"/></svg>');
background-size: 0.7em;
background-repeat: no-repeat;
background-position: right 1rem center;
}
label {
display: block;
text-transform: uppercase;
margin: 0 0 1rem;
letter-spacing: 0.1rem;
}
h2 {
text-transform: uppercase;
letter-spacing: 0.1rem;
margin: 5rem 0 2.5rem;
}
<section class="list-section">
<h2>Filterable Item List</h2>
<form>
<label for="filter">Sort by tag</label>
<select name="filter">
<option>All</option>
<option>Example Tag</option>
<option>Test</option>
</select>
</form>
<ul class="item-list">
<li class="card" data-tags="['Example Tag', 'Test']">
<h3>Card Title</h3>
<p>Description</p>
<ul class="tags">
<li>Example Tag</li>
<li>Test</li>
</ul>
</li>
<li class="card" data-tags="['Test']">
<h3>Card Title</h3>
<p>Description</p>
<ul class="tags">
<li>Test</li>
</ul>
</li>
<li class="card" data-tags="['Example Tag', 'Test']">
<h3>Card Title</h3>
<p>Description</p>
<ul class="tags">
<li>Example Tag</li>
<li>Test</li>
</ul>
</li>
<li class="card" data-tags="['Example Tag']">
<h3>Card Title</h3>
<p>Description</p>
<ul class="tags">
<li>Example Tag</li>
</ul>
</li>
</ul>
</section>
<section class="list-section">
<h2>Filterable Item List</h2>
<form>
<label for="filter">Sort by tag</label>
<select name="filter">
<option>All</option>
<option>Example Tag</option>
<option>Test</option>
</select>
</form>
<ul class="item-list">
<li class="card" data-tags="['Example Tag', 'Test']">
<h3>Card Title</h3>
<p>Description</p>
<ul class="tags">
<li>Example Tag</li>
<li>Test</li>
</ul>
</li>
<li class="card" data-tags="['Test']">
<h3>Card Title</h3>
<p>Description</p>
<ul class="tags">
<li>Test</li>
</ul>
</li>
<li class="card" data-tags="['Example Tag', 'Test']">
<h3>Card Title</h3>
<p>Description</p>
<ul class="tags">
<li>Example Tag</li>
<li>Test</li>
</ul>
</li>
<li class="card" data-tags="['Example Tag']">
<h3>Card Title</h3>
<p>Description</p>
<ul class="tags">
<li>Example Tag</li>
</ul>
</li>
</ul>
</section>
// Function to sort a list by tag
function sortList() {
// Get all sections with filterable lists
let sections = document.querySelectorAll(".list-section");
// Set up logic for each section
sections.forEach(section => {
// Get list of all list items
let items = section.querySelectorAll(".item-list > li");
// Get the filter select input and add listener for the change event
let select = section.querySelector("select");
select.addEventListener("change", sort);
// Actually sorting the cards
function sort() {
// Look at each item in the array
items.forEach(element => {
// Remove the "hidden" attribute if the item has the tag selected or if the selection is "All"
// Otherwise, add the hidden attribute to the element
if (element.dataset.tags.includes(select.value) | select.value == "All") {
element.removeAttribute("hidden");
} else { element.setAttribute("hidden", true); }
});
};
// perform the sort funtion on initialization to cover edge cases, such as the user refreshing the page
sort();
});
}
// Initialize the list sorting function. This should be called on every page where a filterable list is available.
sortList();
@MattMcAdams
Copy link
Author

This is a super rough concept for sorting a list of tagged items with javascript. HTML structure could probably be improved and the CSS can be scrapped in favor of styles that match the project of course.

Features the ability to have multiple filterable lists that function independently on a single page and each item may have more than one tag.

@MattMcAdams
Copy link
Author

I need to close some chrome tabs and don't have time to digest this info right now, so here's some accessibility notes:

I think it would also be useful to test this page using VoiceOver just to see how it will actually be read / navigated by disabled users:

  • Test keyboard navigation
  • Test with voiceover

https://webaim.org/articles/voiceover/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment