Learn to create a tag-based filter using HTML, CSS, and JavaScript. Step-by-step instructions for building a modern, responsive filter system.
Table of Contents
Filtering content on a webpage can help make it user-friendly and easy to navigate. In this blog, we will go step-by-step on how to create a tag-based filter using HTML, CSS, and JavaScript. By the end of this tutorial, you will have a clean and modern UI for your filtering system that shows or hides content based on selected tags.
Prerequisites
Before we get started, make sure you have the following:
- Basic knowledge of HTML for structuring the page.
- Understanding of CSS for styling and layout.
- Basic JavaScript to add interactivity to the filter.
If you are familiar with these technologies, you're all set to begin!
Source Code
Step 1 (HTML Code):
First, we need to create the basic structure for the tags and content items. Here’s a breakdown of its main components:
1. <!DOCTYPE html>
This defines the document type and version of HTML (HTML5 in this case).
2. <html lang="en">
This starts the HTML document with the language attribute set to English.
3. <head>
Contains metadata and external resources for the page:
<meta charset="UTF-8">
: Sets the character encoding to UTF-8.<meta name="viewport" content="width=device-width, initial-scale=1.0">
: Ensures the page is responsive on all devices.<title>Tag Based Filter</title>
: Sets the title of the page, which appears in the browser tab.<link rel="stylesheet" href="https://fonts.googleapis.com/...">
: Imports the Poppins font from Google Fonts.<link rel="stylesheet" href="styles.css">
: Links an external CSS file (styles.css
) to style the page.
4. <body>
Contains the visible content of the page.
a) Tag Filter Buttons (div.tag-filter
)
This section displays filter buttons (like "All," "HTML," "CSS," etc.). These buttons are assigned data-filter
attributes that correspond to categories such as HTML, CSS, JavaScript, Python, etc.
- The
All
button has the classactive
, meaning it will be the selected filter by default. - Other buttons allow users to filter items based on specific programming languages or technologies.
b) Grid of Projects (div.grid-container
)
This section displays various project categories in a grid format. Each project is inside a div.grid-item
, which represents a single project.
- Each project item has a
data-category
attribute, specifying which categories it belongs to. For example:- HTML and CSS Projects:
data-category="html css"
- Python Projects:
data-category="javascript python"
- HTML and CSS Projects:
- The content of each project includes:
- An image (
<img>
) related to the project. - A heading (
<h3>
) displaying the project name. - Filter buttons (
<button class="filter-btn">
): These show which categories (HTML, CSS, JavaScript, etc.) the project belongs to.
- An image (
c) External Script (<script src="script.js"></script>
)
This includes an external JavaScript file (script.js
), which handles the logic for filtering the projects based on the selected tags.
Step 2 (CSS Code):
Now, let's make the filter buttons and content look nice. Here's a breakdown of each section:
1. Global body
Style
body {
font-family: 'Poppins', Arial, sans-serif;
margin: 0;
padding: 20px;
}
- font-family: The default font for the page is set to
'Poppins'
. If it's unavailable, it falls back toArial
or a generic sans-serif font. - margin: 0: Removes the default margin around the body.
- padding: 20px: Adds 20px padding to the body for spacing.
2. Tag Filter Container (.tag-filter
)
.tag-filter {
display: flex;
flex-wrap: wrap;
margin-bottom: 20px;
}
- display: flex: Displays the filter tags in a flexible row layout.
- flex-wrap: wrap: Ensures that the tags wrap to the next line if they don't fit in a single row.
- margin-bottom: 20px: Adds space below the tag filter section.
3. Tag Button (.tag
)
.tag {
font-family: 'Poppins', Arial, sans-serif;
padding: 5px 10px;
margin: 5px;
border: none;
background-color: #dadada;
cursor: pointer;
border-radius: 5px;
transition: background-color 0.3s, color 0.3s;
}
- font-family: Similar to the body, it sets the font for individual tags.
- padding: Adds padding inside each tag to create space around the text.
- margin: Adds space around the tag button.
- border: none: Removes the default border.
- background-color: Default background is a light grey (
#dadada
). - cursor: pointer: Changes the cursor to a pointer when hovered, indicating it's clickable.
- border-radius: Rounds the corners of each tag.
- transition: Adds a smooth transition effect for background and text color changes (e.g., when a tag becomes active).
4. Active Tag Styles
The active
class is applied to tags when selected, with different colors for each category (e.g., "html," "css," etc.).
.tag[data-filter="all"].active {
background-color: #4CAF50;
color: white;
}
- This applies to tags with the
data-filter="all"
andactive
class. It changes the background color to green and the text to white when active. - The same pattern is used for other tags (e.g., "html," "javascript," etc.) with different colors for each.
5. Grid Container (.grid-container
)
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 15px;
}
- display: grid: Creates a grid layout to display the filtered content.
- grid-template-columns: Uses
auto-fill
to create as many columns as possible, with each column having a minimum width of 220px and flexible maximum width. - gap: Adds a 15px gap between grid items.
6. Grid Items (.grid-item
)
.grid-item {
background-color: white;
border: 1px solid #ccc;
border-radius: 5px;
padding: 15px;
text-align: center;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
- background-color: White background for each grid item.
- border: A light grey border around each item.
- border-radius: Rounds the corners of grid items.
- padding: Adds inner spacing.
- text-align: center: Centers the text within each item.
- box-shadow: Adds a subtle shadow for a slight depth effect.
7. Grid Item Images (.grid-item img
)
.grid-item img {
width: 100%;
height: auto;
border-radius: 5px;
}
- width: 100%: Ensures the image takes the full width of the container.
- height: auto: Maintains the aspect ratio of the image.
- border-radius: Adds rounded corners to the image.
8. Filter Buttons (.filter-btn
)
.filter-btn {
padding: 5px 10px;
margin: 5px;
border: none;
cursor: pointer;
border-radius: 5px;
transition: background-color 0.3s, color 0.3s;
}
- Styles are similar to
.tag
buttons, allowing users to filter content using different buttons.
9. Specific Filter Button Colors
The filter buttons have different colors for each type (e.g., Python, HTML, JavaScript):
.filter-btn[data-filter="python"] {
background-color: #FF5722;
}
- Each filter button gets a unique background color based on the
data-filter
attribute.
10. Hidden Class (.hidden
)
.hidden {
display: none;
}
- display: none: Used to hide elements, typically for filtered-out content. When a tag filter is applied, the corresponding grid items not matching the filter get this class.
body {
font-family: 'Poppins', Arial, sans-serif;
margin: 0;
padding: 20px;
}
.tag-filter {
display: flex;
flex-wrap: wrap;
margin-bottom: 20px;
}
.tag {
font-family: 'Poppins', Arial, sans-serif;
padding: 5px 10px;
margin: 5px;
border: none;
background-color: #dadada;
cursor: pointer;
border-radius: 5px;
transition: background-color 0.3s, color 0.3s;
}
.tag[data-filter="all"].active {
background-color: #4CAF50;
color: white;
}
.tag[data-filter="html"].active {
background-color: #2196F3;
color: white;
}
.tag[data-filter="javascript"].active {
background-color: #FF9800;
color: white;
}
.tag[data-filter="css"].active {
background-color: #9C27B0;
color: white;
}
.tag[data-filter="python"].active {
background-color: #FF5722;
color: white;
}
.tag[data-filter="c"].active {
background-color: #4CAF50;
color: white;
}
.tag[data-filter="csharp"].active {
background-color: #009688;
color: white;
}
.tag[data-filter="react"].active {
background-color: #795548;
color: white;
}
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 15px;
}
.grid-item {
background-color: white;
border: 1px solid #ccc;
border-radius: 5px;
padding: 15px;
text-align: center;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.grid-item img {
width: 100%;
height: auto;
border-radius: 5px;
}
.filter-buttons {
margin-top: 10px;
}
.filter-btn {
padding: 5px 10px;
margin: 5px;
border: none;
cursor: pointer;
border-radius: 5px;
transition: background-color 0.3s, color 0.3s;
}
.filter-btn[data-filter="python"] {
background-color: #FF5722;
}
.filter-btn[data-filter="html"] {
background-color: #2196F3;
}
.filter-btn[data-filter="c"] {
background-color: #4CAF50;
}
.filter-btn[data-filter="javascript"] {
background-color: #FF9800;
}
.filter-btn[data-filter="csharp"] {
background-color: #009688;
}
.filter-btn[data-filter="css"] {
background-color: #9C27B0;
}
.filter-btn[data-filter="react"] {
background-color: #795548;
}
.hidden {
display: none;
}
Step 3 (JavaScript Code):
Now we will add the JavaScript code to make the filter buttons interactive. The buttons will control which content is visible based on the tags selected. Here's an explanation of each part of the code:
1. Selecting Elements
const tags = document.querySelectorAll('.tag');
const gridItems = document.querySelectorAll('.grid-item');
tags
: Selects all elements with the class.tag
, which are used as filters.gridItems
: Selects all elements with the class.grid-item
, which are the items displayed in the grid that will be filtered.
2. Filter Function (filterItems
)
const filterItems = (filter) => {
gridItems.forEach(item => {
if (filter === 'all' || item.getAttribute('data-category').includes(filter)) {
item.classList.remove('hidden');
} else {
item.classList.add('hidden');
}
});
};
- filterItems(filter): This function filters the grid items based on the provided filter.
- It loops through each grid item.
- If the filter is
'all'
(show all items) or the item'sdata-category
attribute includes the filter, the grid item is shown by removing thehidden
class. - If the filter doesn't match, the item is hidden by adding the
hidden
class.
3. Handling Tag Click Events
tags.forEach(tag => {
tag.addEventListener('click', () => {
tags.forEach(btn => btn.classList.remove('active'));
tag.classList.add('active');
const filter = tag.getAttribute('data-filter');
filterItems(filter);
});
});
- tags.forEach(tag => { ... }): Loops through all the tags and adds an event listener for the
click
event.- When a tag is clicked:
- First, all tags are deactivated by removing the
active
class. - Then, the clicked tag is activated by adding the
active
class to it. - The filter value (from the
data-filter
attribute) is retrieved from the clicked tag. - Finally, the
filterItems
function is called with the filter value to show/hide the appropriate grid items.
- First, all tags are deactivated by removing the
- When a tag is clicked:
4. Handling Filter Button Click Events
document.querySelectorAll('.filter-btn').forEach(button => {
button.addEventListener('click', () => {
const filter = button.getAttribute('data-filter');
tags.forEach(tag => tag.classList.remove('active'));
const correspondingTag = document.querySelector(`.tag[data-filter="${filter}"]`);
if (correspondingTag) {
correspondingTag.classList.add('active');
}
filterItems(filter);
});
});
- This section handles clicks on filter buttons (elements with the class
.filter-btn
).- When a filter button is clicked:
- The filter value is retrieved from the button's
data-filter
attribute. - All tags are deactivated by removing the
active
class. - The tag that corresponds to the button's filter (matching the
data-filter
value) is activated by adding theactive
class. - The
filterItems
function is called with the filter value to show/hide the appropriate grid items.
- The filter value is retrieved from the button's
- When a filter button is clicked:
const tags = document.querySelectorAll('.tag');
const gridItems = document.querySelectorAll('.grid-item');
const filterItems = (filter) => {
gridItems.forEach(item => {
if (filter === 'all' || item.getAttribute('data-category').includes(filter)) {
item.classList.remove('hidden');
} else {
item.classList.add('hidden');
}
});
};
tags.forEach(tag => {
tag.addEventListener('click', () => {
tags.forEach(btn => btn.classList.remove('active'));
tag.classList.add('active');
const filter = tag.getAttribute('data-filter');
filterItems(filter);
});
});
document.querySelectorAll('.filter-btn').forEach(button => {
button.addEventListener('click', () => {
const filter = button.getAttribute('data-filter');
tags.forEach(tag => tag.classList.remove('active'));
const correspondingTag = document.querySelector(`.tag[data-filter="${filter}"]`);
if (correspondingTag) {
correspondingTag.classList.add('active');
}
filterItems(filter);
});
});
Final Output:
Conclusion:
In this blog, we covered how to create a tag-based filter using HTML, CSS, and JavaScript. This feature is useful for filtering content on websites with multiple categories, like portfolios, blogs, or product pages. With a simple setup and clean code, you can easily adapt this to suit your needs.
Tag-based filters provide a smooth user experience and are an excellent way to make your content more organized and accessible.
That’s a wrap!
I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊