javascripthtmlcss

I want to design a web image gallery with css grid in a particular way and I'm stuck


  1. I wanted to have only 6 images under the main-image, but at the same time I want to have more than 6 images / total.. the 1st problem is whenever I add another image is creating a new row, it's not creating it on the same row - I only want to have 2 rows the one with the main image and the one with the 6 images ( with ONLY six images )

  2. How do I have multiple images in that "slider" underneath, without having to have them all at the same time but to see them gradually as the user clicks through them? I want only 6 images in the slider but more in total so when the user gets to the 6th image, the next 6 images load, while the previous 6 images hide, and when it gets to the last image to go back to the first and vice versa.

I tried added images then hiding them with overflow:hidden (before I get into the js I need to get through this one first).

I'm kind of a beginner so on the 2nd problem I have no clue where to start, but if someone could just point me in the right direction it would be very nice for me.

html {
  font-size: 62.5%;
  box-sizing: border-box;
  /* font-family: "Montserrat", sans-serif; */
}

body {
  margin: 0;
  padding: 0;
  font-family: "Montserrat", sans-serif;
  font-optical-sizing: auto;
  font-weight: 500;
  font-style: normal;
  background-color: #e9e9e9;
}

figure {
  display: block;

  margin: 0;
  padding: 0;

  height: 100%;
  width: 100%;
}

.grid {
  display: grid;

}

.grid__gallery {
  max-width: 100%;

  padding: .5rem;

  margin-left: 2rem;
  margin-right: 2rem;

  column-gap: 0.4rem;
  row-gap: 0.1rem;

  grid-template-columns: repeat(6, 1fr);
  grid-template-rows: auto;

}

.main__image {
  position: relative;
  width: 100%;
  color: white;
  background-color: #444;

  height: 50rem;


  grid-column: 1 / -1;

  /* this will helps changing the photo */
  /* by selecting the url of one of the photos under the  main slide and passing it in the background image of this css */
  background-image: url("");
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
}

.image {
  max-width: 100%;
  width: 100%;

  cursor: pointer;
  transition: 0.1s ease;


  background-color: #333;
  border: 1px solid green;
  height: 15rem;
}

.slide:active {
  cursor: pointer;
  transform: scale(0.995);
  box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.041);
}

.slider-arrow {
  font-size: 3rem;
  position: absolute;
  cursor: pointer;
  padding: 1rem;
  border-radius: 10%;

  transition: 0.3s ease;
  border: 0.1rem solid transparent;
  outline: none;
}

.slider-arrow:active {
  font-size: 2.8rem;
}

.slider-arrow:hover {
  border: 0.1rem solid #fff;
}

.left-arrow {
  top: 50%;
  left: 5%;
  transform: translateY(-50%);
}

.right-arrow {
  top: 50%;
  right: 5%;
  transform: translateY(-50%);
}
<div class="grid grid__gallery">
  <div class="main__image">
    <div class="left-arrow slider-arrow">&larr;</div>
    <div class="right-arrow slider-arrow">&rarr;</div>
  </div>
  <figure class="image slide__1"><img src="" alt="1" /></figure>
  <figure class="image slide__2"><img src="" alt="2" /></figure>
  <figure class="image slide__3"><img src="" alt="3" /></figure>
  <figure class="image slide__4"><img src="" alt="4" /></figure>
  <figure class="image slide__5"><img src="" alt="5" /></figure>
  <figure class="image slide__6"><img src="" alt="6" /></figure>
</div>


Solution

  • CSS grid will not help in your specific case. You need to create a separate flex container for your thumbnails. Then, you could simply use Element.scrollIntoView() to its inline center.

    const mod = (n, m) => ((n % m) + m) % m; // Fix negative Modulo
    
    const gallery = (elGallery) => {
      let c = 0; // current index
      const elImage = elGallery.querySelector(".image");
      const elPrev = elGallery.querySelector(".prev");
      const elNext = elGallery.querySelector(".next");
      const elNav = elGallery.querySelector(".nav");
      const elsThumbs = elNav.querySelectorAll(".thumb");
      const tot = elsThumbs.length;
      const goto = (i) => { c = mod(i, tot); anim(c); };
      const prev = () => goto(--c);
      const next = () => goto(++c);
      const anim = () => {
        elImage.src = elsThumbs[c].src;
        elsThumbs[c].scrollIntoView({
          behavior: "smooth",
          block: "nearest",
          inline: "center"
        });
        elNav.querySelector(".is-active")?.classList.remove("is-active");
        elsThumbs[c].classList.add("is-active");
      };
      // Events
      elsThumbs.forEach((elThumb, i) => {elThumb.addEventListener("click", (evt) => goto(i));});
      elPrev.addEventListener("click", prev);
      elNext.addEventListener("click", next);
      // Init
      goto(c);
    };
    
    document.querySelectorAll(".gallery").forEach(gallery);
    * { margin: 0; box-sizing: border-box; }
    
    body {
      font: 62.5%/1.4 system-ui, sans-serif;
    }
    
    .gallery {
      
      --height: 15rem;
      --nav-height: 8rem;
      position: relative;
      background: #222;
    
      .image {
        display: block;
        width: 100%;
        height: var(--height);
        object-fit: cover;
      }
    
      .prev, .next {
        position: absolute;
        top: calc(50% - var(--nav-height) / 2);
        cursor: pointer;
        padding: 1rem;
        border-radius: 10%;
        transform: translateY(-50%);
        border: none;
        outline: none;
    
        &.prev {
          left: 5%;
        }
    
        &.next {
          right: 5%;
        }
      }
    
      .nav {
        display: flex;
        overflow-x: auto;
        height: var(--nav-height);
        
        img {
          width: 16.666%;
          height: 100%;
          object-fit: cover;
          opacity: 0.4;
          transition: all 0.3s;
          cursor: pointer;
          &.is-active {
            opacity: 1;
            border: 5px solid #fff;
          }
        }
      }
    }
    <div class="gallery">
      <img class="image">
      <button type="button" class="prev">&larr;</button>
      <button type="button" class="next">&rarr;</button>
      <div class="nav">
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/237/300/200" alt="1" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/238/300/200" alt="2" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/239/300/200" alt="3" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/231/300/200" alt="4" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/232/300/200" alt="5" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/233/300/200" alt="6" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/137/300/200" alt="1" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/338/300/200" alt="2" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/139/300/200" alt="3" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/131/300/200" alt="4" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/132/300/200" alt="5" />
        <img class="thumb" loading="lazy" src="https://picsum.photos/id/133/300/200" alt="6" />
      </div>
    </div>