Search code examples
javascriptcssanimationcss-animations

CSS/JS Slider Animation Loop with Sequential Slide Positions


I want to implement a CSS/JS slider that should do the following

  1. There should be 2 or more div
  2. It should show the first div for 3 seconds on load, then the first div should get replaced with second, second with third and so on...
  3. Animation must come in a sequence (right, bottom, left, top...)
  4. Animation should be played in loop
  5. Each div must show for 3 seconds and then show the next slide

I have tried the following code: https://codesandbox.io/s/nostalgic-dewdney-lnz8kr?file=/index.html

I have few issues with the code such as, it does not play in loop, and there is a difference in duration of each slide, where am I going wrong here?


Solution

  • I would change classes. Something like this:

    document.querySelectorAll('.slider-container').forEach(slider => {
      const delay = Number(slider.dataset.delay) || 0;
      const transitionDuration = Number(slider.dataset.transitionDuration) || 400;
      let autoplayDelay = Number(slider.dataset.autoplayDelay) || 3000;
      if (autoplayDelay - transitionDuration < 100) {
        autoplayDelay = transitionDuration + 100;
      }
      
      const classes = ['from-right', 'from-bottom', 'from-left', 'from-top'];
      let nextClassIndex = -1;
      
      setTimeout(() => {
        setTimeout(() => {
          slide();
          setInterval(slide, autoplayDelay);
         }, autoplayDelay)
      }, delay);
      
      function slide() {
        const activeSlide = slider.querySelector('.slide.active');
        const nextSlide = activeSlide.nextElementSibling ?? slider.querySelector('.slide:first-child');
        const animationClass = classes[nextClassIndex + 1];
        nextClassIndex++;
        if (nextClassIndex === classes.length - 1) {
          nextClassIndex = -1;
        }
        
        classes.map(className => activeSlide.classList.remove(className));
        activeSlide.style.removeProperty('transition-duration');
        activeSlide.style.removeProperty('z-index');
        
        nextSlide.classList.add(animationClass);
        nextSlide.style.transitionDuration = transitionDuration + 'ms';
        nextSlide.style.zIndex = 6;
        nextSlide.classList.add('active');
         
        setTimeout(() => nextSlide.classList.add('animated'), 100)
        setTimeout(() => activeSlide.classList.remove('active', 'animated'), transitionDuration + 100 );
      }
    })
    .slider-container {
      position: relative;
      width: 200px;
      height: 200px;
      overflow: hidden;
    }
    
    .slide {
      position: absolute;
      inset:0;
      transition-property: transform;
      will-change: transform;
      display:none;
    }
    
    .slide.from-right {
      transform: translateX(100%);
    }
    
    .slide.from-left {
      transform: translateX(-100%);
    }
    
    .slide.from-top {
      transform: translateY(-100%);
    }
    
    .slide.from-bottom {
      transform: translateY(100%);
    }
    
    .slide.animated {
      transform: none;
    }
    
    .slide.active {
      display: block
    }
    <div class="slider-container">
      <div class="slide active" style="background-color: red;">0</div>
      <div class="slide" style="background-color: blue;">1</div>
     </div>
    <div
      class="slider-container"
      data-delay="2000"
      data-transition-duration="800"
    >
      <div class="slide active" style="background-color: red;">0</div>
      <div class="slide" style="background-color: blue;">1</div>
      <div class="slide" style="background-color: green;">2</div>
      <div class="slide" style="background-color: yellow;">3</div>
      <div class="slide" style="background-color: brown;">4</div>
      <div class="slide" style="background-color: red;">5</div>
      <div class="slide" style="background-color: blue;">6</div>
      <div class="slide" style="background-color: green;">7</div>
     </div>