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:

  1. Basic knowledge of HTML for structuring the page.
  2. Understanding of CSS for styling and layout.
  3. 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"
  • 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.
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.

				
					<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tag Based Filter</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap">
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="tag-filter">
        <button class="tag active" data-filter="all">All</button>
        <button class="tag" data-filter="html">HTML</button>
        <button class="tag" data-filter="css">CSS</button>
        <button class="tag" data-filter="javascript">JavaScript</button>
        <button class="tag" data-filter="python">Python</button>
        <button class="tag" data-filter="c">C</button>
        <button class="tag" data-filter="csharp">C#</button>
        <button class="tag" data-filter="react">React</button>
    </div>
    <div class="grid-container">
        <div class="grid-item" data-category="html css">
            <img decoding="async" data-src="https://www.codewithfaraz.com/img/Collection%20of%20100%20HTML%20and%20CSS%20Mini%20Projects%20for%20Beginners%20with%20Source%20Code.jpg" alt="Tech Image" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazyload"><noscript><img decoding="async" src="https://www.codewithfaraz.com/img/Collection%20of%20100%20HTML%20and%20CSS%20Mini%20Projects%20for%20Beginners%20with%20Source%20Code.jpg" alt="Tech Image"></noscript>
            <h3>HTML and CSS Projects</h3>
            <div class="filter-buttons">
                <button class="filter-btn" data-filter="html">HTML</button>
                <button class="filter-btn" data-filter="css">CSS</button>
            </div>
        </div>
        <div class="grid-item" data-category="html css javascript">
            <img decoding="async" src="https://www.codewithfaraz.com/img/50%20HTML,%20CSS,%20and%20JavaScript%20Projects%20with%20Source%20Code%20for%20Beginners.jpg" alt="javascript Image">
            <h3>HTML, CSS, and JavaScript Projects</h3>
            <div class="filter-buttons">
                <button class="filter-btn" data-filter="html">HTML</button>
                <button class="filter-btn" data-filter="css">CSS</button>
                <button class="filter-btn" data-filter="javascript">JavaScript</button>
            </div>
        </div>
        <div class="grid-item" data-category="html css react">
            <img decoding="async" data-src="https://www.codewithfaraz.com/img/25-react-projects-for-beginners-with-source-code.webp" alt="react Image" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazyload"><noscript><img decoding="async" src="https://www.codewithfaraz.com/img/25-react-projects-for-beginners-with-source-code.webp" alt="react Image"></noscript>
            <h3>React Projects</h3>
            <div class="filter-buttons">
                <button class="filter-btn" data-filter="html">HTML</button>
                <button class="filter-btn" data-filter="css">CSS</button>
                <button class="filter-btn" data-filter="react">React</button>
            </div>
        </div>
        <div class="grid-item" data-category="javascript python">
            <img decoding="async" data-src="https://www.codewithfaraz.com/img/50+%20Python%20Projects%20with%20Source%20Code%20Beginner%20to%20Advanced.jpg" alt="python Image" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazyload"><noscript><img decoding="async" src="https://www.codewithfaraz.com/img/50+%20Python%20Projects%20with%20Source%20Code%20Beginner%20to%20Advanced.jpg" alt="python Image"></noscript>
            <h3>Python Projects</h3>
            <div class="filter-buttons">
                <button class="filter-btn" data-filter="javascript">JavaScript</button>
                <button class="filter-btn" data-filter="python">Python</button>
            </div>
        </div>
        <div class="grid-item" data-category="c csharp">
            <img decoding="async" data-src="https://www.codewithfaraz.com/img/20-c-language-mini-projects-with-source-code.webp" alt="c Image" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazyload"><noscript><img decoding="async" src="https://www.codewithfaraz.com/img/20-c-language-mini-projects-with-source-code.webp" alt="c Image"></noscript>
            <h3>C Mini Projects</h3>
            <div class="filter-buttons">
                <button class="filter-btn" data-filter="c">C</button>
                <button class="filter-btn" data-filter="csharp">C#</button>
            </div>
        </div>
        <div class="grid-item" data-category="c csharp">
            <img decoding="async" data-src="https://www.codewithfaraz.com/projects/csharp-projects-with-source-code-for-beginners.webp" alt="csharp Image" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazyload"><noscript><img decoding="async" src="https://www.codewithfaraz.com/projects/csharp-projects-with-source-code-for-beginners.webp" alt="csharp Image"></noscript>
            <h3>C# Projects</h3>
            <div class="filter-buttons">
                <button class="filter-btn" data-filter="c">C</button>
                <button class="filter-btn" data-filter="csharp">C#</button>
            </div>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>
				
			

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.

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.
				
					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:

create-tag-based-filter-using-html-css-and-javascript.gif

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.