Responsive Image Lightbox using HTML CSS & JavaScript

Hey friends, today in this blog you’ll learn how to create Responsive Image Lightbox using HTML CSS & JavaScript.
You may have seen image lightbox on many websites. Lightbox showcases images and videos by filling the screen and dimming out the rest of the web page. In the image lightbox, there are slide controls so you can easily change the image to next or previous. There are many JavaScript libraries for lightbox but today in this blog I’ll show you how to create lightbox without using the JavaScript library or jQuery plugin.

In this program [Responsive Image Lightbox], there are six images on the webpage and when you click on the particular image then the lightbox appears with the selected image. In the lightbox, there is a total image and current image number on the top left side and a cross icon to the top right side. There are also previous and next icons to change the image. When you click on the cross icon then the lightbox will disappear and after again clicking on the particular image, the lightbox appears.
This image gallery and lightbox are fully responsive for all devices. On the pc, there are 3 three images in the single row but on the mobile devices, there is only one image in the single row.

If you’re feeling difficulty to understanding what I’m saying then you can Try the code below to check the output yourself.Still facing issues? Feel free to mail us your queries on info@vikashtech.com

HTML

<!DOCTYPE html>
<!-- Created By Praveen Kumar - www.vikashtech.com -->
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!--- Don't forget to add this meta tag otherwise your design won't responsive ---->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!--- <title>Responsive Image Lightbox | VikashTech</title> ---->
    <link rel="stylesheet" href="blog.css">
    <script src="https://kit.fontawesome.com/a076d05399.js"></script>
</head>
<body>
  <div class="wrapper">
    <div class="gallery">
       <div class="image"><span><img src="gallery.jpg" alt=""></span></div> 
       <div class="image"><span><img src="Screenshot (11).png" alt=""></span></div>
      <div class="image"><span><img src="Screenshot (12).png" alt=""></span></div>  
       <div class="image"><span><img src="Screenshot (13).png" alt=""></span></div> 
       <div class="image"><span><img src="Screenshot (14).png" alt=""></span></div> 
       <div class="image"><span><img src="Screenshot (15).png" alt=""></span></div> 
    </div>
  </div>
  <div class="preview-box">
    <div class="details">
      <span class="title">Image <p class="current-img"></p> of <p class="total-img"></p></span>
      <span class="icon fas fa-times"></span>
    </div>
    <div class="image-box">
      <div class="slide prev"><i class="fas fa-angle-left"></i></div>
      <div class="slide next"><i class="fas fa-angle-right"></i></div>
      <img src="" alt="">
    </div>
  </div>
  <div class="shadow"></div>

   <script src="script.js"></script> 

</body>
</html>

CSS

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
::selection{
  color: #fff;
  background: #007bff;
}
body{
  padding: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}
.wrapper{
  max-width: 1100px;
}
.gallery{
  display: flex;
  flex-wrap: wrap;
}
.gallery .image{
  padding: 7px;
  width: calc(100% / 3);
}
.gallery .image span{
  display: flex;
  width: 100%;
  overflow: hidden;
}
.gallery .image img{
  width: 100%;
  vertical-align: middle;
  transition: all 0.3s ease;
}
.gallery .image:hover img{
  transform: scale(1.1);
}

.preview-box{
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.9);
  background: #fff;
  max-width: 700px;
  width: 100%;
  z-index: 5;
  opacity: 0;
  pointer-events: none;
  border-radius: 3px;
  padding: 0 5px 5px 5px;
  box-shadow: 0px 0px 15px rgba(0,0,0,0.2);
}
.preview-box.show{
  opacity: 1;
  pointer-events: auto;
  transform: translate(-50%, -50%) scale(1);
  transition: all 0.3s ease;
}
.preview-box .details{
  display: flex;
  align-items: center;
  padding: 12px 15px 12px 10px;
  justify-content: space-between;
}
.preview-box .details .title{
  display: flex;
  font-size: 18px;
  font-weight: 400;
}
.details .title p{
  margin: 0 5px;
}
.details .title p.current-img{
  font-weight: 500;
}
.details .icon{
  color: #007bff;
  font-size: 20px;
  cursor: pointer;
}
.preview-box .image-box{
  display: flex;
  width: 100%;
  position: relative;
}
.image-box .slide{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  color: #fff;
  font-size: 30px;
  cursor: pointer;
  height: 50px;
  width: 60px;
  line-height: 50px;
  text-align: center;
  border-radius: 3px;
}
.slide.prev{
  left: 0px;
}
.slide.next{
  right: 0px;
}
.image-box img{
  width: 100%;
  border-radius: 0 0 3px 3px;
}
.shadow{
  position: fixed;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  z-index: 2;
  display: none;
  background: rgba(0,0,0,0.45);
}

@media(max-width: 1000px){
  .gallery .image{
    width: calc(100% / 2);
  }
}
@media(max-width: 600px){
  .gallery .image{
    width: 100%;
    padding: 4px;
  }
}

Javascript

//getting all required elements
const gallery  = document.querySelectorAll(".image"),
previewBox = document.querySelector(".preview-box"),
previewImg = previewBox.querySelector("img"),
closeIcon = previewBox.querySelector(".icon"),
currentImg = previewBox.querySelector(".current-img"),
totalImg = previewBox.querySelector(".total-img"),
shadow = document.querySelector(".shadow");

window.onload = ()=>{
    for (let i = 0; i < gallery.length; i++) {
        totalImg.textContent = gallery.length; //passing total img length to totalImg variable
        let newIndex = i; //passing i value to newIndex variable
        let clickedImgIndex; //creating new variable
        
        gallery[i].onclick = () =>{
            clickedImgIndex = i; //passing cliked image index to created variable (clickedImgIndex)
            function preview(){
                currentImg.textContent = newIndex + 1; //passing current img index to currentImg varible with adding +1
                let imageURL = gallery[newIndex].querySelector("img").src; //getting user clicked img url
                previewImg.src = imageURL; //passing user clicked img url in previewImg src
            }
            preview(); //calling above function
    
            const prevBtn = document.querySelector(".prev");
            const nextBtn = document.querySelector(".next");
            if(newIndex == 0){ //if index value is equal to 0 then hide prevBtn
                prevBtn.style.display = "none"; 
            }
            if(newIndex >= gallery.length - 1){ //if index value is greater and equal to gallery length by -1 then hide nextBtn
                nextBtn.style.display = "none"; 
            }
            prevBtn.onclick = ()=>{ 
                newIndex--; //decrement index
                if(newIndex == 0){
                    preview(); 
                    prevBtn.style.display = "none"; 
                }else{
                    preview();
                    nextBtn.style.display = "block";
                } 
            }
            nextBtn.onclick = ()=>{ 
                newIndex++; //increment index
                if(newIndex >= gallery.length - 1){
                    preview(); 
                    nextBtn.style.display = "none";
                }else{
                    preview(); 
                    prevBtn.style.display = "block";
                }
            }
            document.querySelector("body").style.overflow = "hidden";
            previewBox.classList.add("show"); 
            shadow.style.display = "block"; 
            closeIcon.onclick = ()=>{
                newIndex = clickedImgIndex; //assigning user first clicked img index to newIndex
                prevBtn.style.display = "block"; 
                nextBtn.style.display = "block";
                previewBox.classList.remove("show");
                shadow.style.display = "none";
                document.querySelector("body").style.overflow = "scroll";
            }
        }
        
    }
    
}

Responsive Filterable Image Gallery using HTML CSS & JavaScript

Hey friends, today in this blog you’ll learn how to create a Responsive Filterable Image Gallery using HTML CSS & JavaScript.
A filterable image gallery means you can display as many images as you want. The most important feature of Filterable Image Gallery is that you will have the control to categorize all the pictures or images based on the specified parameter.
In this design [Responsive Filterable Image Gallery], there are a total of eight images on the webpage with the filter names navbar on the top. These images are specified to the different categories, when you click on the bag, there is only appear the bag related image, and when you click on the watch, there will appear watch related images only. Each image has a click event mean when you click on the particular image, that image will appear in a full image preview box with the category name and there is also a cross icon, so you can easily dismiss or close the preview box.
If you’re feeling difficult to understand what I am saying. You can try Own with below code copy and paste it.

HTML

<!DOCTYPE html>
<!-- Created By praveen kumar - www.vikashtech.com -->
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- <title>Filterable Image Gallery | VikashTech</title> -->
    <link rel="stylesheet" href="blog.css">
   
    <script src="https://kit.fontawesome.com/a076d05399.js"></script>
</head>
<body>
  <div class="wrapper">
    <!-- filter Items -->
    <nav>
      <div class="items">
        <span class="item active" data-name="all">All</span>
        <span class="item" data-name="bag">Bag</span>
        <span class="item" data-name="shoe">Shoe</span>
        <span class="item" data-name="watch">Watch</span>
        <span class="item" data-name="camera">Camera</span>
        <span class="item" data-name="headphone">Headphone</span>
      </div>
    </nav>
    <!-- filter Images -->
    <div class="gallery">
     <div class="image" data-name="bag"><span><img src="Screenshot (7).png" alt=""></span></div>
       <div class="image" data-name="headphone"><span><img src="Screenshot (16).png" alt=""></span></div> 
      <div class="image" data-name="camera"><span><img src="Screenshot (10).png" alt=""></span></div> 
       <div class="image" data-name="shoe"><span><img src="Screenshot (8).png" alt=""></span></div> 
     <div class="image" data-name="headphone"><span><img src="Screenshot (14).png" alt=""></span></div>
       <div class="image" data-name="watch"><span><img src="Screenshot (13).png" alt=""></span></div> 
       <div class="image" data-name="shoe"><span><img src="Screenshot (12).png" alt=""></span></div> 
       <div class="image" data-name="camera"><span><img src="Screenshot (11).png" alt=""></span></div> 
    </div>
  </div>
  <!-- fullscreen img preview box -->
  <div class="preview-box">
    <div class="details">
      <span class="title">Image Category: <p></p></span>
      <span class="icon fas fa-times"></span>
    </div>
    <div class="image-box"><img src="" alt=""></div>
  </div>
  <div class="shadow"></div>

   <script src="script.js"></script> 

</body>
</html>

CSS

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
::selection{
  color: #fff;
  background: #007bff;
}
body{
  padding: 10px;
}
.wrapper{
  margin: 100px auto;
  max-width: 1100px;
}
.wrapper nav{
  display: flex;
  justify-content: center;
}
.wrapper .items{
  display: flex;
  max-width: 720px;
  width: 100%;
  justify-content: space-between;
}
.items span{
  padding: 7px 25px;
  font-size: 18px;
  font-weight: 500;
  cursor: pointer;
  color: #007bff;
  border-radius: 50px;
  border: 2px solid #007bff;
  transition: all 0.3s ease;
}
.items span.active,
.items span:hover{
  color: #fff;
  background: #007bff;
}

.gallery{
  display: flex;
  flex-wrap: wrap;
  margin-top: 30px;
}
.gallery .image{
  width: calc(100% / 4);
  padding: 7px;
}
.gallery .image span{
  display: flex;
  width: 100%;
  overflow: hidden;
}
.gallery .image img{
  width: 100%;
  vertical-align: middle;
  transition: all 0.3s ease;
}
.gallery .image:hover img{
  transform: scale(1.1);
}
.gallery .image.hide{
  display: none;
}
.gallery .image.show{
  animation: animate 0.4s ease;
}
@keyframes animate {
  0%{
    transform: scale(0.5);
  }
  100%{
    transform: scale(1);
  }
}

.preview-box{
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.9);
  background: #fff;
  max-width: 700px;
  width: 100%;
  z-index: 5;
  opacity: 0;
  pointer-events: none;
  border-radius: 3px;
  padding: 0 5px 5px 5px;
  box-shadow: 0px 0px 15px rgba(0,0,0,0.2);
}
.preview-box.show{
  opacity: 1;
  pointer-events: auto;
  transform: translate(-50%, -50%) scale(1);
  transition: all 0.3s ease;
}
.preview-box .details{
  padding: 13px 15px 13px 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.details .title{
  display: flex;
  font-size: 18px;
  font-weight: 400;
}
.details .title p{
  font-weight: 500;
  margin-left: 5px;
}
.details .icon{
  color: #007bff;
  font-style: 22px;
  cursor: pointer;
}
.preview-box .image-box{
  width: 100%;
  display: flex;
}
.image-box img{
  width: 100%;
  border-radius: 0 0 3px 3px;
}
.shadow{
  position: fixed;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  z-index: 2;
  display: none;
  background: rgba(0,0,0,0.4);
}
.shadow.show{
  display: block;
}

@media (max-width: 1000px) {
  .gallery .image{
    width: calc(100% / 3);
  }
}
@media (max-width: 800px) {
  .gallery .image{
    width: calc(100% / 2);
  }
}
@media (max-width: 700px) {
  .wrapper nav .items{
    max-width: 600px;
  }
  nav .items span{
    padding: 7px 15px;
  }
}
@media (max-width: 600px) {
  .wrapper{
    margin: 30px auto;
  }
  .wrapper nav .items{
    flex-wrap: wrap;
    justify-content: center;
  }
  nav .items span{
    margin: 5px;
  }
  .gallery .image{
    width: 100%;
  }
}

JS

//selecting all required elements
const filterItem = document.querySelector(".items");
const filterImg = document.querySelectorAll(".gallery .image");

window.onload = ()=>{ //after window loaded
  filterItem.onclick = (selectedItem)=>{ //if user click on filterItem div
    if(selectedItem.target.classList.contains("item")){ //if user selected item has .item class
      filterItem.querySelector(".active").classList.remove("active"); //remove the active class which is in first item
      selectedItem.target.classList.add("active"); //add that active class on user selected item
      let filterName = selectedItem.target.getAttribute("data-name"); //getting data-name value of user selected item and store in a filtername variable
      filterImg.forEach((image) => {
        let filterImges = image.getAttribute("data-name"); //getting image data-name value
        //if user selected item data-name value is equal to images data-name value
        //or user selected item data-name value is equal to "all"
        if((filterImges == filterName) || (filterName == "all")){
          image.classList.remove("hide"); //first remove the hide class from the image
          image.classList.add("show"); //add show class in image
        }else{
          image.classList.add("hide"); //add hide class in image
          image.classList.remove("show"); //remove show class from the image
        }
      });
    }
  }
  for (let i = 0; i < filterImg.length; i++) {
    filterImg[i].setAttribute("onclick", "preview(this)"); //adding onclick attribute in all available images
  }
}

//fullscreen image preview function
//selecting all required elements
const previewBox = document.querySelector(".preview-box"),
categoryName = previewBox.querySelector(".title p"),
previewImg = previewBox.querySelector("img"),
closeIcon = previewBox.querySelector(".icon"),
shadow = document.querySelector(".shadow");

function preview(element){
  //once user click on any image then remove the scroll bar of the body, so user cant scroll up or down
  document.querySelector("body").style.overflow = "hidden";
  let selectedPrevImg = element.querySelector("img").src; //getting user clicked image source link and stored in a variable
  let selectedImgCategory = element.getAttribute("data-name"); //getting user clicked image data-name value
  previewImg.src = selectedPrevImg; //passing the user clicked image source in preview image source
  categoryName.textContent = selectedImgCategory; //passing user clicked data-name value in category name
  previewBox.classList.add("show"); //show the preview image box
  shadow.classList.add("show"); //show the light grey background
  closeIcon.onclick = ()=>{ //if user click on close icon of preview box
    previewBox.classList.remove("show"); //hide the preview box
    shadow.classList.remove("show"); //hide the light grey background
    document.querySelector("body").style.overflow = "auto"; //show the scroll bar on body
  }
}