javascripthtml

Multiple lightbox galleries


I know next to nothing about JavaScript, so I'm not sure what I'm even doing, but I'm trying to make a page with multiple image galleries that opens up a lightbox when you click one of the pics.

I got it to work with only one gallery, but when I added the second one, the images open the lightbox for the first gallery instead of the current one.

Here's the code for what I was able to do so far (I got the code for the lightbox at W3Schools and modified it a bit):

const lightboxes = document.querySelectorAll(".lightbox");

function openLightbox() {
  lightboxes.forEach(lightbox => {
    document.querySelector('.lightbox').style.display = "block";
    document.querySelector('body').style.overflowY = "hidden";
  });
}

function closeLightbox() {
  lightboxes.forEach(lightbox => {
    const lightClose = document.querySelector('.close');
    const lightContent = document.querySelector('.lightbox-content');

    if (lightClose.contains(event.target) || !lightContent.contains(event.target)) {
      lightbox.style.display = "none";
      document.querySelector('body').style.overflowY = "visible";
    }
  }); 
}

var slideIndex = 1;
showSlides(slideIndex);

function plusSlides(n) {
  showSlides(slideIndex += n);
}

function currentSlide(n) {
  showSlides(slideIndex = n);
}

function showSlides(n) {
  lightboxes.forEach(lightbox => {
    var i;
    var slides = document.getElementsByClassName("mySlides");
    if (n > slides.length) {slideIndex = 1;}
    if (n < 1) {slideIndex = slides.length;}
    for (i = 0; i < slides.length; i++) {
      slides[i].style.display = "none";
    }

    slides[slideIndex-1].style.display = "block";
  });
}
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 1vw;
  max-width: 100vw; /* Recommended */
  margin: 1vw auto;
  padding: 1vw;
}

.gallery figure {
  display: flex;
  justify-items: center;
  height: 180px;
  margin: 0;
  
  img {
    width: 100%;
    object-fit: cover;
    object-position: center;
  }
}

img:hover {
  cursor: pointer;
}

.lightbox {
  display: none;
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: #ffffffee;
  align-content: center;
  justify-items: center;
}

.lightbox-content {
  position: relative;
  width: 80vh;
  justify-items: center;
  align-content: center;
  z-index: 100;
  grid-gap: 5vh;
  margin-bottom: 10vh;
  
  figure {
    display: flex;
    flex-flow: column;
    margin: 0;
  }
  
  figure img {
    max-height: 60vh;
    object-fit: contain;
  }
}

.imgcap {
  width: min-content;
}

figcaption {
  height: 40px;
}

.mySlides {
  display: none;
  grid-gap: 1vh;
}

.prev, .next, .close {
  position: absolute;
  color: black;
  font-weight: bold;
  font-size: 40px;
  font: 700 40px;
  cursor: pointer;
  align-content: center;
  text-shadow: 2px 2px 4px #00000064;
  opacity: 0.6;
  transition: 0.3s ease;
}

.close {
  position: relative;
  float: right;
  margin-right: -30px;
  margin-top: 10px;
  z-index: 1000;
}

.next {
  right: 0;
  padding-left: 50%;
}

.prev {
  padding-right: 50%;
}

.next, .prev {
  top: 5%;
  height: 80%;
  margin: 0 -8vh;
}

.prev:before {
  content: '\3008';
}

.close:before {
  content: '\2A2F';
}

.next:before {
  content: '\3009';
}

/* Number text (1/3 etc) */
.numbertext {
  color: black;
  font: 700 1em;
  text-align: center;
}

:where(.prev, .next, .close):hover {
  opacity: 1;
}

@media screen and (max-width: 650px) {
  .lightbox-content {
    width: 80vw;
    max-width: none;
    figure img {
      max-width: none;
      height: 60vw;
    }
  }
  
  .next, .prev {
    margin: 0 -8vh;
  }
}
<!-- gallery 1 -->
    <section class="gallery">
      <figure>
        <img src="https://placehold.co/500x300/000/cyan?text=1" onclick="openLightbox();currentSlide(1)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/cyan?text=2" onclick="openLightbox();currentSlide(2)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/cyan?text=3" onclick="openLightbox();currentSlide(3)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/cyan?text=4" onclick="openLightbox();currentSlide(4)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/cyan?text=5" onclick="openLightbox();currentSlide(5)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/cyan?text=6" onclick="openLightbox();currentSlide(6)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/cyan?text=7" onclick="openLightbox();currentSlide(7)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/cyan?text=8" onclick="openLightbox();currentSlide(8)"/>
      </figure>
    </section>

    <!-- lightbox for gallery 1 -->
    <div class="lightbox" onclick="closeLightbox()">
      <div class="lightbox-content">
        <div class="imgcap">
          <span class="close" onclick="closeLightbox()"></span>
          <figure class="mySlides">
            <p class="numbertext">1 / 8</p>
            <img src="https://placehold.co/500x300/000/cyan?text=1"/>
            <figcaption>first cyan</figcaption>
          </figure>

          <figure class="mySlides">
            <div class="numbertext">2 / 8</div>
            <img src="https://placehold.co/500x300/000/cyan?text=2"/>
            <figcaption>second cyan</figcaption>
          </figure>

          <figure class="mySlides">
            <div class="numbertext">3 / 8</div>
            <img src="https://placehold.co/500x300/000/cyan?text=3">
            <figcaption>third cyan</figcaption>
          </figure>

          <figure class="mySlides">
            <div class="numbertext">4 / 8</div>
            <img src="https://placehold.co/500x300/000/cyan?text=4">
            <figcaption>fourth cyan</figcaption>
          </figure>
          
          <figure class="mySlides">
            <div class="numbertext">5 / 8</div>
            <img src="https://placehold.co/500x300/000/cyan?text=5">
            <figcaption>fifth cyan</figcaption>
          </figure>
          
          <figure class="mySlides">
            <div class="numbertext">6 / 8</div>
            <img src="https://placehold.co/500x300/000/cyan?text=6">
            <figcaption>sixth cyan</figcaption>
          </figure>
          
          <figure class="mySlides">
            <div class="numbertext">7 / 8</div>
            <img src="https://placehold.co/500x300/000/cyan?text=7">
            <figcaption>seventh cyan</figcaption>
          </figure>
          
          <figure class="mySlides">
            <div class="numbertext">8 / 8</div>
            <img src="https://placehold.co/500x300/000/cyan?text=8">
            <figcaption>eighth cyan</figcaption>
          </figure>
        </div>        

        <a class="prev" onclick="plusSlides(-1)"><span/></a>
        <a class="next" onclick="plusSlides(1)"><span/></a>
      </div>
    </div>
    
    <!-- gallery 2 -->
    
    <section class="gallery">
      <figure>
        <img src="https://placehold.co/500x300/000/chartreuse?text=1" onclick="openLightbox();currentSlide(1)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/chartreuse?text=2" onclick="openLightbox();currentSlide(2)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/chartreuse?text=3" onclick="openLightbox();currentSlide(3)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/chartreuse?text=4" onclick="openLightbox();currentSlide(4)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/chartreuse?text=5" onclick="openLightbox();currentSlide(5)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/chartreuse?text=6" onclick="openLightbox();currentSlide(6)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/chartreuse?text=7" onclick="openLightbox();currentSlide(7)"/>
      </figure>
      
      <figure>
        <img src="https://placehold.co/500x300/000/chartreuse?text=8" onclick="openLightbox();currentSlide(8)"/>
      </figure>
    </section>

    <!-- lightbox  for gallery 2 -->
    <div class="lightbox" onclick="closeLightbox()">
      
      <div class="lightbox-content">
        <div class="imgcap">
          <span class="close" onclick="closeLightbox()"></span>
          <figure class="mySlides">
            <p class="numbertext">1 / 8</p>
            <img src="https://placehold.co/500x300/000/chartreuse?text=1"/>
            <figcaption>first green</figcaption>
          </figure>

          <figure class="mySlides">
            <div class="numbertext">2 / 8</div>
            <img src="https://placehold.co/500x300/000/chartreuse?text=2"/>
            <figcaption>second green</figcaption>
          </figure>

          <figure class="mySlides">
            <div class="numbertext">3 / 8</div>
            <img src="https://placehold.co/500x300/000/chartreuse?text=3">
            <figcaption>third green</figcaption>
          </figure>

          <figure class="mySlides">
            <div class="numbertext">4 / 8</div>
            <img src="https://placehold.co/500x300/000/chartreuse?text=4">
            <figcaption>fourth green</figcaption>
          </figure>
          
          <figure class="mySlides">
            <div class="numbertext">5 / 8</div>
            <img src="https://placehold.co/500x300/000/chartreuse?text=5">
            <figcaption>fifth green</figcaption>
          </figure>
          
          <figure class="mySlides">
            <div class="numbertext">6 / 8</div>
            <img src="https://placehold.co/500x300/000/chartreuse?text=6">
            <figcaption>sixth green</figcaption>
          </figure>
          
          <figure class="mySlides">
            <div class="numbertext">7 / 8</div>
            <img src="https://placehold.co/500x300/000/chartreuse?text=7">
            <figcaption>seventh green</figcaption>
          </figure>
          
          <figure class="mySlides">
            <div class="numbertext">8 / 8</div>
            <img src="https://placehold.co/500x300/000/chartreuse?text=8">
            <figcaption>eighth green</figcaption>
          </figure>
        </div>

        <a class="prev" onclick="plusSlides(-1)"><span/></a>
        <a class="next" onclick="plusSlides(1)"><span/></a>
      </div>
    </div>

I don't know what I'm doing wrong :^(


Solution

  • Right now both galleries are using the same lightbox code. Since your JavaScript is using querySelector() and getElementsByClassName(), it only grabs the first match. So when you click an image in the second gallery, it still opens the first lightbox.

    let slideIndex = {};
    
    function openLightbox(galleryId) {
      const lightbox = document.querySelector(`.lightbox[data-gallery="${galleryId}"]`);
      lightbox.style.display = "block";
      document.body.style.overflowY = "hidden";
      if (!slideIndex[galleryId]) slideIndex[galleryId] = 1;
      showSlides(slideIndex[galleryId], galleryId);
    }
    
    function closeLightbox(galleryId) {
      const lightbox = document.querySelector(`.lightbox[data-gallery="${galleryId}"]`);
      lightbox.style.display = "none";
      document.body.style.overflowY = "visible";
    }
    
    function plusSlides(n, galleryId) {
      showSlides(slideIndex[galleryId] += n, galleryId);
    }
    
    function currentSlide(n, galleryId) {
      showSlides(slideIndex[galleryId] = n, galleryId);
    }
    
    function showSlides(n, galleryId) {
      const slides = document.querySelectorAll(`.lightbox[data-gallery="${galleryId}"] .mySlides`);
      if (n > slides.length) slideIndex[galleryId] = 1;
      if (n < 1) slideIndex[galleryId] = slides.length;
      slides.forEach(slide => slide.style.display = "none");
      slides[slideIndex[galleryId] - 1].style.display = "block";
    }
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    
    .gallery {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      grid-gap: 1vw;
      max-width: 100vw;
      /* Recommended */
      margin: 1vw auto;
      padding: 1vw;
    }
    
    .gallery figure {
      display: flex;
      justify-items: center;
      height: 180px;
      margin: 0;
    
      img {
        width: 100%;
        object-fit: cover;
        object-position: center;
      }
    }
    
    img:hover {
      cursor: pointer;
    }
    
    .lightbox {
      display: none;
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      background-color: #ffffffee;
      align-content: center;
      justify-items: center;
    }
    
    .lightbox-content {
      position: relative;
      width: 80vh;
      justify-items: center;
      align-content: center;
      z-index: 100;
      grid-gap: 5vh;
      margin-bottom: 10vh;
    
      figure {
        display: flex;
        flex-flow: column;
        margin: 0;
      }
    
      figure img {
        max-height: 60vh;
        object-fit: contain;
      }
    }
    
    .imgcap {
      width: min-content;
    }
    
    figcaption {
      height: 40px;
    }
    
    .mySlides {
      display: none;
      grid-gap: 1vh;
    }
    
    .prev,
    .next,
    .close {
      position: absolute;
      color: black;
      font-weight: bold;
      font-size: 40px;
      font: 700 40px;
      cursor: pointer;
      align-content: center;
      text-shadow: 2px 2px 4px #00000064;
      opacity: 0.6;
      transition: 0.3s ease;
    }
    
    .close {
      position: relative;
      float: right;
      margin-right: -30px;
      margin-top: 10px;
      z-index: 1000;
    }
    
    .next {
      right: 0;
      padding-left: 50%;
    }
    
    .prev {
      padding-right: 50%;
    }
    
    .next,
    .prev {
      top: 5%;
      height: 80%;
      margin: 0 -8vh;
    }
    
    .prev:before {
      content: '\3008';
    }
    
    .close:before {
      content: '\2A2F';
    }
    
    .next:before {
      content: '\3009';
    }
    
    /* Number text (1/3 etc) */
    .numbertext {
      color: black;
      font: 700 1em;
      text-align: center;
    }
    
    :where(.prev, .next, .close):hover {
      opacity: 1;
    }
    
    @media screen and (max-width: 650px) {
      .lightbox-content {
        width: 80vw;
        max-width: none;
    
        figure img {
          max-width: none;
          height: 60vw;
        }
      }
    
      .next,
      .prev {
        margin: 0 -8vh;
      }
    }
    <!-- gallery 1 -->
    <section class="gallery" data-gallery="1">
      <figure><img src="https://placehold.co/500x300/000/cyan?text=1" onclick="openLightbox(1);currentSlide(1,1)"/></figure>
      <figure><img src="https://placehold.co/500x300/000/cyan?text=2" onclick="openLightbox(1);currentSlide(2,1)"/></figure>
      <figure><img src="https://placehold.co/500x300/000/cyan?text=3" onclick="openLightbox(1);currentSlide(3,1)"/></figure>
      <figure><img src="https://placehold.co/500x300/000/cyan?text=4" onclick="openLightbox(1);currentSlide(4,1)"/></figure>
    </section>
    
    <div class="lightbox" data-gallery="1">
      <div class="lightbox-content">
        <span class="close" onclick="closeLightbox(1)">×</span>
    
        <figure class="mySlides">
          <p class="numbertext">1 / 4</p><img src="https://placehold.co/500x300/000/cyan?text=1"/>
          <figcaption>first cyan</figcaption>
        </figure>
        <figure class="mySlides">
          <p class="numbertext">2 / 4</p><img src="https://placehold.co/500x300/000/cyan?text=2"/>
          <figcaption>second cyan</figcaption>
        </figure>
        <figure class="mySlides">
          <p class="numbertext">3 / 4</p><img src="https://placehold.co/500x300/000/cyan?text=3"/>
          <figcaption>third cyan</figcaption>
        </figure>
        <figure class="mySlides">
          <p class="numbertext">4 / 4</p><img src="https://placehold.co/500x300/000/cyan?text=4"/>
          <figcaption>fourth cyan</figcaption>
        </figure>
    
        <a class="prev" onclick="plusSlides(-1,1)">❮</a>
        <a class="next" onclick="plusSlides(1,1)">❯</a>
      </div>
    </div>
    
    <!-- gallery 2 -->
    <section class="gallery" data-gallery="2">
      <figure><img src="https://placehold.co/500x300/000/chartreuse?text=1" onclick="openLightbox(2);currentSlide(1,2)"/></figure>
      <figure><img src="https://placehold.co/500x300/000/chartreuse?text=2" onclick="openLightbox(2);currentSlide(2,2)"/></figure>
      <figure><img src="https://placehold.co/500x300/000/chartreuse?text=3" onclick="openLightbox(2);currentSlide(3,2)"/></figure>
      <figure><img src="https://placehold.co/500x300/000/chartreuse?text=4" onclick="openLightbox(2);currentSlide(4,2)"/></figure>
    </section>
    
    <div class="lightbox" data-gallery="2">
      <div class="lightbox-content">
        <span class="close" onclick="closeLightbox(2)">×</span>
    
        <figure class="mySlides">
          <p class="numbertext">1 / 4</p><img src="https://placehold.co/500x300/000/chartreuse?text=1"/>
          <figcaption>first green</figcaption>
        </figure>
        <figure class="mySlides">
          <p class="numbertext">2 / 4</p><img src="https://placehold.co/500x300/000/chartreuse?text=2"/>
          <figcaption>second green</figcaption>
        </figure>
        <figure class="mySlides">
          <p class="numbertext">3 / 4</p><img src="https://placehold.co/500x300/000/chartreuse?text=3"/>
          <figcaption>third green</figcaption>
        </figure>
        <figure class="mySlides">
          <p class="numbertext">4 / 4</p><img src="https://placehold.co/500x300/000/chartreuse?text=4"/>
          <figcaption>fourth green</figcaption>
        </figure>
    
        <a class="prev" onclick="plusSlides(-1,2)">❮</a>
        <a class="next" onclick="plusSlides(1,2)">❯</a>
      </div>
    </div>