arrow_back
View code

<div class="gallery">
        <div class="preview">
            <img src="https://dynaimage.cdn.cnn.com/cnn/q_auto,w_900,c_fill,g_auto,h_506,ar_16:9/http%3A%2F%2Fcdn.cnn.com%2Fcnnnext%2Fdam%2Fassets%2F210826215454-10-china-luxury-domestic-travelers-photos.jpg" alt="" />  
            <div class="mob-trigger">
                <span class="material-icons">notes</span>
                <div>
                    <div>View gallery</div>
                    <div>3 photos</div>
                </div>
            </div>
        </div>
        <div class="slider-container">
            <header>
                <div class="counter">
                    <span class="material-icons">notes</span>
                    <span class="count">1/7</span>
                </div>
                <div class="actions">
                    <span class="hide-captions">Hide caption</span>
                    <span class="material-icons close">close</span>
                </div>
            </header>
        <div class="slider transition">
          <ul>
            <li class="active">
              <img src="https://dynaimage.cdn.cnn.com/cnn/q_auto,w_900,c_fill,g_auto,h_506,ar_16:9/http%3A%2F%2Fcdn.cnn.com%2Fcnnnext%2Fdam%2Fassets%2F210826215454-10-china-luxury-domestic-travelers-photos.jpg" alt="" />
              <div class="description">
                <div class="text">
                    <strong>Sanya, Hainan province:</strong> According to the 2021 Hurun Report, Sanya -- a tropical playground on the island of Hainan south of mainland China -- is the most popular destination among wealthy domestic travelers these days. Click on to see more popular Chinese destinations.
                </div>
                    <div class="subtitle">Chen Wenwu/Oriental Image/Reuters</div>
               </div>
            </li>
            <li>
              <img src="https://dynaimage.cdn.cnn.com/cnn/q_auto,w_900,c_fill,g_auto,h_506,ar_16:9/http%3A%2F%2Fcdn.cnn.com%2Fcnnnext%2Fdam%2Fassets%2F210826215210-03-china-luxury-domestic-travelers-photos-restricted.jpg" alt="" />
              <div class="description">
                <div class="text">
                    <strong>Yunnan province:</strong> Tourists visit Laojun Mountain in China's Yunnan province on April 10, 2020. The mountainous area is a popular destination thanks to an abundance of ancient cities, forests and tea plantations.
                </div>
                <div class="subtitle">Li Ming/Imaginechina/AP</div>
            </li>
            <li>
              <img src="https://dynaimage.cdn.cnn.com/cnn/q_auto,w_900,c_fill,g_auto,h_506,ar_16:9/http%3A%2F%2Fcdn.cnn.com%2Fcnnnext%2Fdam%2Fassets%2F210826215142-02-china-luxury-domestic-travelers-photos.jpgv" alt="" />
              <div class="description">
                <div class="text">
                    <strong>Sichuan:</strong> A giant panda plays at the Shenshuping Base of the China Conservation and Research Center for the Giant Panda in Wolong National Nature Reserve on August 4, 2021 in Sichuan province.
                </div>
                <div class="subtitle">An Yuan/China News Service/Getty Images</div>
            </li>
          </ul>
        </div>
        <div class="arrows">
          <span class="material-icons prev">
      arrow_circle_left
      </span>
          <span class="material-icons next">
      arrow_circle_right
      </span>
        </div>
        <div class="back-action">
            <button class="cdt-btn cdt-btn-primary cdt-full-width">Back</button>
        </div>
    </div>
    <footer >
        <div class="counter">
            <span class="material-icons">notes</span>
            <span class="count">1/7</span>
        </div>
        <div class="description">
            <div class="caption active">
                <div class="text">
                    <strong>Sanya, Hainan province:</strong> According to the 2021 Hurun Report, Sanya -- a tropical playground on the island of Hainan south of mainland China -- is the most popular destination among wealthy domestic travelers these days. Click on to see more popular Chinese destinations.
                </div>
                <div class="subtitle">Chen Wenwu/Oriental Image/Reuters</div>
            </div>
            <div class="caption">
                <div class="text">
                    <strong>Yunnan province:</strong> Tourists visit Laojun Mountain in China's Yunnan province on April 10, 2020. The mountainous area is a popular destination thanks to an abundance of ancient cities, forests and tea plantations.
                </div>
                <div class="subtitle">Li Ming/Imaginechina/AP</div>
            </div>
            <div class="caption">
                <div class="text">
                    <strong>Sichuan:</strong> A giant panda plays at the Shenshuping Base of the China Conservation and Research Center for the Giant Panda in Wolong National Nature Reserve on August 4, 2021 in Sichuan province.
                </div>
                <div class="subtitle">An Yuan/China News Service/Getty Images</div>
            </div>
        </div>
    </footer>
      </div>
                        
Copy HTML

/*
 * File: _advanced-carousel.scss
 * Location /src/scss/components
 * Advanced carousel component
 */

@import url("https://fonts.googleapis.com/icon?family=Material+Icons");

.gallery {
  flex-direction: column;
  position: relative;
  overflow: hidden;
  @media screen and (max-width: 1024px) {
    width: 100%;
    padding-top: 60px;
    overflow: initial;
  }
  .slider-container {
    position: relative;
    .slider {
      &.transition {
        transition: transform 0.5s;
        transition-timing-function: ease-in-out;
        @media screen and (max-width: 1024px) {
          padding: 0 10px;
        }
      }
      ul {
        margin: 0;
        padding: 0;
        list-style: none;
        display: flex;
        li {
          img {
            opacity: 0.5;
            transition: opacity 0.3s;
          }
          &.active {
            img {
              opacity: 1;
            }
          }
          .description {
            display: none;
          }
        }
        @media screen and (max-width: 1024px) {
          flex-wrap: wrap;
          width: 100%;
          li {
            margin-top: 40px;
            width: 100%;
            img {
              width: 100%;
              opacity: 1;
            }
            .description {
              display: block;
              &.hide {
                display: none;
              }
              margin-top: 10px;
              .text {
                font-size: 14px;
              }
              .subtitle {
                margin-top: 10px;
                color: var(--color-mid);
                font-size: 12px;
              }
            }
          }
        }
      }
    }
    @media screen and (max-width: 1024px) {
      background: var(--color-bg);
      margin-top: 20px;
      display: none;
      &.show {
        display: block;
      }
      width: 100%;
      position: absolute;
      top: 0;
      z-index: 2;
    }
  }
  .arrows {
    width: calc(900px - 32px);
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    justify-content: space-between;
    span {
      color: var(--color-bg);
      font-size: 40px;
      cursor: pointer;
      user-select: none;
    }
    @media screen and (max-width: 1024px) {
      display: none;
    }
  }
  header {
    position: fixed;
    display: none;
    align-items: center;
    background-color: var(--color-bg);
    z-index: 1;
    padding: 0 20px;
    top: 0;
    width: 100%;
    @media screen and (max-width: 1024px) {
      display: flex;
      align-items: center;
      justify-content: space-between;
      border-bottom: 1px solid var(--color-lower);
      .counter {
        padding: 10px 0;
      }
    }
    .actions {
      @media screen and (max-width: 1024px) {
        display: flex;
        align-items: center;
        span {
          border-right: 1px solid var(--color-lower);
          padding: 20px;
          cursor: pointer;
        }
      }
    }
  }
  footer {
    width: 900px;
    margin: 0 auto;
    padding: 20px 0;
    .description {
      .caption {
        display: none;
        &.active {
          display: block;
        }
        padding-top: 20px;
        .text {
          font-size: 14px;
        }
        .subtitle {
          margin-top: 10px;
          font-size: 12px;
          color: var(--color-mid);
        }
      }
    }
    @media screen and (max-width: 1024px) {
      width: 100%;
      display: none;
    }
  }
  header .counter,
  footer .counter {
    padding: 10px 0;
    display: flex;
    align-items: center;
    .count {
      font-variant-numeric: tabular-nums;
      margin-left: 5px;
    }
  }
  .preview {
    width: 100%;
    position: relative;
    cursor: pointer;
    padding: 0 10px;
    display: none;
    @media screen and (max-width: 1024px) {
      display: block;
    }
    &:hover {
      div {
        background-color: var(--color-mid);
      }
    }
    img {
      width: 100%;
    }
    > div {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background-color: var(--color-lowest);
      padding: 10px 20px;
      border-radius: 5px;
      align-items: center;
      display: flex;
      > div {
        margin-left: 5px;
        div:last-child {
          color: var(--color-lower);
        }
      }
    }
  }
  .back-action {
    display: none;
    @media screen and (max-width: 1024px) {
      padding: 10px;
      display: block;
    }
  }
}

                        
Copy SCSS

/*
 * File: advanced-carousel.js
 * Location /src/js/components
 * Advanced carousel component
*/

(function () {
  const desktopBreakpoint = 1024; // should match media query in css
  const gallery = document.querySelector(".gallery");
  const sliderContainer = document.querySelector(".gallery .slider-container");
  const slider = document.querySelector(".gallery .slider");
  const mobDescriptions = document.querySelectorAll(
    ".gallery .slider .description"
  );
  const descriptionCaptions = document.querySelectorAll(
    ".gallery footer .description .caption"
  );
  const headerCount = document.querySelector(".gallery header .count");
  const footerCount = document.querySelector(".gallery footer .count");
  const mobTrigger = document.querySelector(".gallery .mob-trigger");
  const backActionBtn = document.querySelector(".gallery .back-action button");
  const close = document.querySelector(".gallery header .close");
  const hideCaptions = document.querySelector(".gallery header .hide-captions");
  const totalCount = document.querySelector(".gallery .slider ul")
    .childElementCount;
  let currentCount = 0;
  const prev = document.querySelector(".gallery .prev");
  const next = document.querySelector(".gallery .next");
  const imageWidth = 900;
  const containerWidth = gallery.offsetWidth;
  let translate = 900 - (containerWidth - imageWidth) / 2;
  let dir;
  let canMove = true;

  window.addEventListener(
    "scroll",
    Kodhus.Utils.elementInexInView(
      sliderContainer.querySelectorAll("img"),
      -100,
      (index) => (headerCount.innerHTML = `${index}/${totalCount}`)
    )
  );

  mobTrigger.addEventListener("click", () => {
    sliderContainer.classList.add("show");
  });

  backActionBtn.addEventListener("click", () => {
    sliderContainer.classList.remove("show");
  });
  close.addEventListener("click", () => {
    sliderContainer.classList.remove("show");
  });

  if (gallery.offsetWidth > 1024) {
    window.addEventListener("keydown", (e) => {
      if (e.code === "ArrowRight") {
        nextAction();
      }
      if (e.code === "ArrowLeft") {
        prevAction();
      }
    });
  }

  hideCaptions.addEventListener("click", () => {
    mobDescriptions.forEach((desc) => desc.classList.toggle("hide"));
    let hide = true;
    if (hideCaptions.getAttribute("data-state")) {
      hide = !(hideCaptions.getAttribute("data-state") === "true");
    }
    hideCaptions.setAttribute("data-state", hide);
    hideCaptions.innerHTML = hide ? "Show caption" : "Hide caption";
  });

  const setInitialSliderTransform = () => {
    if (gallery.offsetWidth >= 1024) {
      slider.style.transform = `translate3d(-${translate}px, 0, 0)`;
    } else {
      slider.style.transform = `translate3d(-${0}px, 0, 0)`;
    }
  };
  setInitialSliderTransform();
  window.addEventListener("resize", () => {
    setInitialSliderTransform();
  });

  headerCount.innerHTML = `${currentCount + 1}/${totalCount}`;
  footerCount.innerHTML = `${currentCount + 1}/${totalCount}`;

  // add the last element to the first
  if (gallery.offsetWidth >= 1024) {
    const lastPic = document
      .querySelector(".gallery ul li:last-child")
      .cloneNode(true);
    document.querySelector(".gallery ul").prepend(lastPic);
    document.querySelector(".gallery ul li:last-child").remove();
    slider.style.transform = `translate3d(-${translate}px, 0, 0)`;
  }
  const prevAction = () => {
    if (!canMove) return;
    canMove = false;
    descriptionCaptions.forEach((caption) =>
      caption.classList.remove("active")
    );
    currentCount = currentCount - 1 >= 0 ? currentCount - 1 : 2;
    descriptionCaptions[currentCount % totalCount].classList.add("active");
    footerCount.innerHTML = `${(currentCount % totalCount) + 1}/${totalCount}`;
    // add the first to the last
    const lastPic = document
      .querySelector(".gallery ul li:last-child")
      .cloneNode(true);
    document.querySelector(".gallery ul").prepend(lastPic);
    slider.classList.remove("transition");
    slider.style.transform = `translate3d(-${translate + 900}px, 0, 0)`;
    dir = "next";
    document.querySelector(".gallery ul li.active").classList.remove("active");
    document
      .querySelector(".gallery ul li:nth-child(2)")
      .classList.add("active");
    setTimeout(() => {
      slider.classList.add("transition");
      slider.style.transform = `translate3d(-${translate}px, 0, 0)`;
      slider.addEventListener("transitionend", onTransitionEnd);
    });
  };
  const nextAction = () => {
    if (!canMove) return;
    canMove = false;
    descriptionCaptions.forEach((caption) =>
      caption.classList.remove("active")
    );
    currentCount++;
    descriptionCaptions[currentCount % totalCount].classList.add("active");
    footerCount.innerHTML = `${(currentCount % totalCount) + 1}/${totalCount}`;
    // add the first to the last
    document.querySelector(".gallery ul li.active").classList.remove("active");
    document
      .querySelector(".gallery ul li:nth-child(3)")
      .classList.add("active");
    const firstPic = document
      .querySelector(".gallery ul li:first-child")
      .cloneNode(true);
    document.querySelector(".gallery ul").appendChild(firstPic);
    slider.style.transform = `translate3d(-${translate + imageWidth}px, 0, 0)`;
    dir = "prev";
    slider.addEventListener("transitionend", onTransitionEnd);
  };
  next.addEventListener("click", nextAction);
  const onTransitionEnd = (e) => {
    if (e.propertyName === "transform") {
      if (dir === "prev") {
        document.querySelector(".gallery ul li:first-child").remove();
      }
      if (dir === "next") {
        document.querySelector(".gallery ul li:last-child").remove();
      }
      slider.removeEventListener("transitionend", onTransitionEnd);
      slider.classList.remove("transition");
      slider.style.transform = `translate3d(-${translate}px, 0, 0)`;
      setTimeout(() => {
        slider.classList.add("transition");
        canMove = true;
      });
    }
  };
  prev.addEventListener("click", prevAction);
})();

Copy JS
Upgrade to professional version

Using professional version, you will have unlimited number of projects and unlimited access to materials in Kodhus.com.