Creating an image gallery that allows users to search and filter images by category is a great way to practice basic web development skills. In this tutorial, we’ll walk through the HTML, CSS, and JavaScript that together build a simple but beautiful image gallery.
Video Tutorial:
HTML:
The HTML lays the foundation of our gallery. Inside the <section>
element with the class gallery-section
, we have a container that includes the title, search box, filter buttons, and the gallery itself. Each image in the gallery is wrapped inside a div
with the class gallery-item
. Important attributes like data-category
and data-title
are used to store the image’s category (nature, people, tech) and title, making it easier for JavaScript to filter them later. Overall, the HTML provides a clean, semantic layout that’s easy to style and manipulate.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet" /> <link rel="stylesheet" href="style.css" /> <title>Image Gallery With Search And Filter</title> </head> <body> <section class="gallery-section"> <div class="container"> <h1 class="title">Image Gallery</h1> <div class="controls"> <input type="text" id="searchBox" placeholder="Search images" /> <div class="filter-buttons"> <button class="filter-btn active" data-filter="all">All</button> <button class="filter-btn" data-filter="nature">Nature</button> <button class="filter-btn" data-filter="people">People</button> <button class="filter-btn" data-filter="tech">Tech</button> </div> </div> <div class="gallery" id="gallery"> <!--Nature--> <div class="gallery-item" data-category="nature" data-title="Forest Trail" > <img src="Forest Trail.jpg" alt="Forest Trail" /> <p>Forest Trail</p> </div> <div class="gallery-item" data-category="nature" data-title="Mountain View" > <img src="Mountain View.jpg" alt="Mountain View" /> <p>Mountain View</p> </div> <div class="gallery-item" data-category="nature" data-title="Beach Sunset" > <img src="Beach Sunset.jpg" alt="Beach Sunset" /> <p>Beach Sunset</p> </div> <div class="gallery-item" data-category="nature" data-title="River Stream" alt="River Stream" > <img src="River Stream.jpg" alt="River Stream" /> <p>River Stream</p> </div> <!--Tech--> <div class="gallery-item" data-category="tech" data-title="Laptop Workspace" > <img src="Laptop Workspace.jpg" alt="Laptop Workspace" /> <p>Laptop Workspace</p> </div> <div class="gallery-item" data-category="tech" data-title="Smartphone Setup" > <img src="Smartphone Setup.jpg" alt="Smartphone Setup" /> <p>Smartphone Setup</p> </div> <div class="gallery-item" data-category="tech" data-title="Tech Accesories" > <img src="Tech Accesories.jpg" alt="Tech Accesories" /> <p>Tech Accesories</p> </div> <!-- People --> <div class="gallery-item" data-category="people" data-title="Smiling Woman" > <img src="smiling woman.jpg" alt="Smiling Woman" /> <p>Smiling Woman</p> </div> <div class="gallery-item" data-category="people" data-title="Team Meeting" > <img src="Team Meting.jpg" alt="Team Meeting" /> <p>Team Meeting</p> </div> <div class="gallery-item" data-category="people" data-title="Street Portrait" > <img src="street portrait.jpg" /> <p>Street Potrait</p> </div> </div> </div> </section> <script src="script.js"></script> </body> </html>
CSS:
The CSS makes the gallery look visually appealing and responsive. We start by setting up the body with a nice font (Poppins
) and a light background color. The container is centered with a maximum width and some padding. The controls section is designed with flexbox to stack the search box and buttons nicely. Each button is styled with rounded corners and smooth hover effects. The gallery itself uses CSS columns to automatically arrange images in a responsive, masonry-like grid, adjusting the number of columns based on the screen size. The gallery items have subtle shadows, rounded corners, and padding for a clean, modern appearance.
body { font-family: "Poppins", sans-serif; margin: 0; padding: 0; background-color: #f9fafb; color: #111827; } .container { max-width: 1100px; margin: 0 auto; padding: 2rem; } .title { font-size: 2rem; font-weight: 600; text-align: center; margin-bottom: 2rem; } .controls { display: flex; flex-direction: column; gap: 1rem; margin-bottom: 2rem; } #searchBox { padding: 0.75rem 1rem; width: 100%; max-width: 400px; border: 2px solid #e5e7eb; border-radius: 0.5rem; font-size: 1rem; margin: 0 auto; } .filter-buttons { display: flex; gap: 0.75rem; flex-wrap: wrap; } .filter-btn { padding: 0.5rem 1rem; border: none; background-color: #e5e7eb; border-radius: 20px; cursor: pointer; font-weight: 500; transition: background 0.3s ease; } .filter-btn.active, .filter-btn:hover { background-color: #111827; color: #ffffff; } .gallery { column-count: 1; column-gap: 1.5rem; } @media (min-width: 600px) { .gallery { column-count: 2; } } @media (min-width: 900px) { .gallery { column-count: 3; } } .gallery-item { display: inline-block; width: 100%; margin-bottom: 1.5rem; background: #ffffff; border-radius: 1rem; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); overflow: hidden; text-align: center; transition: transform 0.3s ease; break-inside: avoid; } .gallery-item img { width: 100%; height: auto; display: block; } .gallery-item p { margin: 0; padding: 1rem; font-weight: 500; }
Javascript:
The JavaScript adds interactivity to the gallery. First, we select the search box, filter buttons, and all gallery items. When a user clicks on a filter button, we update which button is active and call the updateGallery()
function, passing in the selected category and search text. Similarly, whenever the user types in the search box, the gallery is updated in real-time. The updateGallery()
function checks if each image matches the selected category and if its title includes the search term. If it matches both, the image is shown; otherwise, it’s hidden. This creates a seamless search and filter experience without reloading the page.
const searchBox = document.getElementById("searchBox"); const filterButtons = document.querySelectorAll(".filter-btn"); const galleryItems = document.querySelectorAll(".gallery-item"); filterButtons.forEach((btn) => { btn.addEventListener("click", () => { document.querySelector(".filter-btn.active").classList.remove("active"); btn.classList.add("active"); const filter = btn.getAttribute("data-filter"); updateGallery(filter, searchBox.value.toLowerCase()); }); }); searchBox.addEventListener("input", () => { const filter = document .querySelector(".filter-btn.active") .getAttribute("data-filter"); updateGallery(filter, searchBox.value.toLowerCase()); }); function updateGallery(category, searchTerm) { galleryItems.forEach((item) => { const matchesCategory = category === "all" || item.dataset.category === category; const matchesSearch = item.dataset.title.toLowerCase().includes(searchTerm); item.style.display = matchesCategory && matchesSearch ? "inline-block" : "none"; }); }
Conclusion
By combining HTML, CSS, and JavaScript, we can easily build an interactive image gallery that looks professional and feels responsive. HTML structures the content, CSS beautifies it, and JavaScript brings it to life with real-time search and category filtering. Projects like these not only strengthen your web development skills but also prepare you to build more complex, dynamic websites in the future. Keep experimenting with more categories, animations, and layout tweaks to make your gallery even more impressive!