Creating a Filterable Image Gallery using JavaScript Tutorial

In this tutorial, you can learn how to create a simple Filterable Image Gallery using HTML, CSS, and JavaScript. The tutorial aims to provide students and beginners with a reference for creating a useful component for a website or web application. Here, a simple web page script will be provided that demonstrates the creation of a filterable image gallery using the said programming markup and languages.

How does the Filterable Image Gallery work?

A Filterable Image Gallery is a web page or a website feature for displaying the images uploaded and related to the site which comes with category filter functionality. Each image that is shown has different categories. Image category filter options are often implemented using buttons, tabs, and dropdown elements.

How to create a Filterable Image Gallery?

The Filterable Image Gallery can be easily achieved using JavaScript. We can simply display the images with an attribute that helps us identify their category. Then using the JS APIs and event listener, we can detect if the gallery is filtered to a specific category which hides the other images that are not equal to the selected category. Check out the simple web application page scripts that I created and provided below to understand more about how to create the Filterable Image Gallery.

Sample Web Page

The scripts below result in a simple web application Image Gallery page. It displays multiple images that are shown in a grid view layout. It has also multiple category buttons above the images container that trigger hide and show images upon filtering them by the selected category. Download and Install a virtual web server such as XAMPP/WAMP so you can run the script on your local machine.

JSON Data

Below is a sample JSON data that contains the image path and their category name. Replace the image paths with the image paths that are available on your end.

  1. [{
  2.     "img_path": "./images/car-1.jpg",
  3.     "category_name": "cars"
  4. },{
  5.     "img_path": "./images/car-2.jpg",
  6.     "category_name": "cars"
  7. },{
  8.     "img_path": "./images/car-3.jpg",
  9.     "category_name": "cars"
  10. },{
  11.     "img_path": "./images/plane-1.jpg",
  12.     "category_name": "planes"
  13. },{
  14.     "img_path": "./images/plane-2.jpg",
  15.     "category_name": "planes"
  16. },{
  17.     "img_path": "./images/plane-3.jpg",
  18.     "category_name": "planes"
  19. },{
  20.     "img_path": "./images/ship-1.jpg",
  21.     "category_name": "ships"
  22. },{
  23.     "img_path": "./images/ship-2.jpg",
  24.     "category_name": "ships"
  25. },{
  26.     "img_path": "./images/ship-3.jpg",
  27.     "category_name": "ships"
  28. }]

Page Interface

Here's the HTML file script named index.html. It contains the page layouts and gallery container elements. I loaded the Bootstrap Framework using CDN which means that an internet connection is a must upon browsing the web page on your browser.

  1. <!DOCTYPE html>
  2. <html lang="en">
  3.     <meta charset="UTF-8">
  4.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>JS - Filterable Gallery</title>
  7.     <link rel="preconnect" href="https://fonts.googleapis.com">
  8.     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  9.     <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200" />
  10.     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
  11.     <link rel="stylesheet" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css">
  12.     <link rel="stylesheet" href="style.css">
  13.     <script src="https://code.jquery.com/jquery-3.6.4.min.js" integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous"></script>
  14.     <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
  15.     <script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
  16. </head>
  17.     <div class="content-md-lg py-3">
  18.         <div class="page-title">Filterable Gallery using CSS and JavaScript</div>
  19.         <hr style="margin:auto; width:25px">
  20.         <div class="col-lg-8 col-md-10 col-sm-12 col-12 mx-auto pt-4 position-relative">
  21.             <div class="container-fluid mb-3" id="category-container"></div>
  22.             <div class="container-fluid" id="gallery-container"></div>
  23.         </div>
  24.     </div>
  25.     <script src="script.js"></script>
  26. </body>
  27. </html>

Stylesheet

Here's the CSS file script named style.css. It contains the styles and the design code of the web page and image containers.

  1. @import url('https://fonts.googleapis.com/css2?family=Courgette&family=Secular+One&display=swap" rel="stylesheet');
  2. :root{
  3.     --secular-font: 'Secular One', sans-serif;
  4. }
  5. *{
  6.     box-sizing: border-box;
  7. }
  8. body *{
  9.     font-family: 'Rubik', sans-serif;
  10. }
  11. /**
  12. Page Design
  13. */
  14. body,
  15. html{
  16.     height: 100%;
  17.     width: 100%;
  18.     margin: 0;
  19.     padding: 0;
  20. }
  21. body{
  22.     background-color: #282A3A;
  23. }
  24. .page-title{
  25.     font-size: 2.5rem;
  26.     font-weight: 500;
  27.     color: #fff;
  28.     letter-spacing: 3px;
  29.     font-family: var(--secular-font);
  30.     text-align: center;
  31.     text-shadow: 0px 0px 3px #2020208c;
  32. }
  33. /* If Galler is empty */
  34. #gallery-container:empty:after{
  35.     content:"No Images found.";
  36.     position: absolute;
  37.     width: 100%;
  38.     font-weight: lighter;
  39.     font-size: 1.2rem;
  40.     font-style: italic;
  41.     text-align: center;
  42. }
  43.  
  44. /* If Galler is not empty */
  45. #gallery-container:not(:empty){
  46.     display: flex;
  47.     flex-wrap: wrap;
  48.     justify-content: space-evenly;
  49. }
  50.  
  51. /* Image Item Container */
  52.  
  53. #gallery-container:not(:empty) .imageItem{
  54.     width: 29%;
  55.     height: 25vh;
  56.     margin-bottom: 1em;
  57. }
  58.  
  59. /* Image Item */
  60. #gallery-container:not(:empty) .imageItem>img{
  61.     width: 100%;
  62.     height: 100%;
  63.     object-fit: cover;
  64.     object-position: center center;
  65. }
  66.  
  67. /* Category Buttons Container */
  68. #category-container{
  69.     display: flex;
  70.     flex-wrap: wrap;
  71.     justify-content: space-between;
  72. }
  73. /* Category Buttons */
  74. button.catbtn {
  75.     width: 30%;
  76.     background: #fff;
  77.     margin-bottom: 1em;
  78.     text-transform: capitalize;
  79.     font-weight: 600;
  80. }
  81. button.catbtn.active {
  82.     background: #0988dd;
  83.     border-color: #0a8ce4;
  84.     color: #fff;
  85. }
  86. button.catbtn:hover{
  87.     color: #292929;
  88.     background: #ebebeb;
  89.     border-color: #dddcdc;
  90. }    

JavaScript

Lastly, here's the JavaScript file script named script.js. It contains the JS codes for loading the images and categories to the web page. It also contains the function that makes the image filtering feature functional.

  1. // Image Item Element
  2. const imageItem = document.createElement('div')
  3.         imageItem.classList.add('imageItem')
  4.         imageItem.innerHTML = `<img src="" alt="">`;
  5.  
  6. // Image Container Selector
  7. const ImageContainer = document.getElementById('gallery-container')
  8. // Image Category Selector
  9. const catContainer = document.getElementById('category-container')
  10.  
  11. // Image Category Button Element
  12. const catBtnItem = document.createElement('button')
  13.         catBtnItem.type = 'button'
  14.         catBtnItem.classList.add('catbtn')
  15.         catBtnItem.classList.add('btn')
  16.         catBtnItem.classList.add('btn-sm')
  17.         catBtnItem.classList.add('rounded-0')
  18.  
  19. let images = {}
  20. let categories = ['all']
  21.  
  22. window.onload = async () =>{
  23.     /**Fetch Gallery Data */
  24.     await fetch('data.json')
  25.     .then(response =>{
  26.         return response.json()
  27.     })
  28.     .then(JSONdata=>{
  29.         images = JSONdata
  30.         Object.values(images).map(image => {
  31.             if(!categories.includes(image.category_name))
  32.             categories.push(image.category_name)
  33.         })
  34.     })
  35.  
  36.     // Load Category Buttons
  37.     await load_categories()
  38.     // Shuffle Image Data
  39.     await shuffleImages()
  40.     // Load Image Data
  41.     await load_images()
  42.  
  43.     catContainer.querySelectorAll('.catbtn').forEach(catBTN => {
  44.         //Add Click Event Listener to Category Button to filter
  45.         catBTN.addEventListener('click', filterGallery.bind(null, catBTN))
  46.     })
  47.    
  48. }
  49.  
  50. //Shuffle Image Data Function
  51. const shuffleImages = () =>{
  52.     var shuffle = images
  53.     for (var i = 0; i  < (shuffle.length - 1); i++ ){
  54.         var k = Math.floor(Math.random() * (i +1));
  55.         var image = shuffle[i]
  56.         shuffle[i] = shuffle[k]
  57.         shuffle[k] = image
  58.     }
  59.     images = shuffle
  60. }
  61.  
  62.  
  63. //Load Category Buttons Function
  64. const load_categories = () =>{
  65.     categories.forEach(category => {
  66.         var btn = catBtnItem.cloneNode(true)
  67.         btn.innerText = category
  68.         catContainer.append(btn)
  69.     })
  70.     catContainer.querySelector('.catbtn:nth-child(1)').classList.add('active')
  71. }
  72.  
  73. //Load Image Items Function
  74. const load_images = () =>{
  75.     images.forEach(image => {
  76.         var item = imageItem.cloneNode(true)
  77.         item.dataset.category=image.category_name
  78.         item.querySelector('img').src = image.img_path
  79.         ImageContainer.appendChild(item)
  80.     });
  81. }
  82.  
  83. // Filter Gallery By selected Category
  84. const filterGallery = (selectedCatBTN) => {
  85.     //Update Active Category Button
  86.     catContainer.querySelectorAll('.catbtn').forEach(catBTN => {
  87.         if(selectedCatBTN == catBTN){
  88.             if(!catBTN.classList.contains('active'))
  89.                 catBTN.classList.add('active');
  90.         }else{
  91.             if(catBTN.classList.contains('active'))
  92.                 catBTN.classList.remove('active');
  93.         }
  94.     })
  95.  
  96.     // Get selected category
  97.     var cat = selectedCatBTN.innerText.toLowerCase()
  98.  
  99.     //Hide Images that category are not equal to selected category
  100.     ImageContainer.querySelectorAll('.imageItem').forEach(item=>{
  101.         if(cat == "all" || cat == item.dataset.category){
  102.             item.style.display = 'block'
  103.         }else{
  104.             item.style.display = 'none'
  105.         }
  106.     })
  107. }

Snapshots

Here are the images or snapshots of the overall result of the scripts that I provided above.

Page Interface (Unfiltered)

Filterable Image Gallery using JavaScript

Filtered Interface (Cars Category)

Filterable Image Gallery using JavaScript

Filtered Interface (Planes Category)

Filterable Image Gallery using JavaScript

DEMO VIDEO

There you go! I have also provided the complete source code zip file that I created for this tutorial and it is free to download on this site. The download button can be found after this tutorial's content. Feel free to download the source code and do some experiments to enhance your programming skills and knowledge.

That's it! I hope this Creating a Filterable Image Gallery using JavaScript Tutorial will help you with what you are looking for and will be useful for your current and future web application projects.

Happy Coding =)

Add new comment