Introduction:Â
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 classÂactive
, 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.
Tag Based Filter
HTML and CSS Projects
HTML, CSS, and JavaScript Projects
React Projects
Python Projects
C Mini Projects
C# Projects
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 toÂArial
 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"
 andÂactive
 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
)
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)
- 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’sÂdata-category
 attribute includes the filter, the grid item is shown by removing theÂhidden
 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 theÂactive
 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.