DEV Community

ktr92
ktr92

Posted on

4

[html js css] Vanilla JS slider with responsivity, swipe, arrows, dots

demo - https://codepen.io/ktr92/pen/gOybmwO

HTML

<div class="myslider" data-myslider-container='sliderID'>
      <div class="myslider__arrows"  data-myslider-arrows='sliderID'>
        <div class="myslider__arrow myslider__left" data-myslider-prev='sliderID'>prev</div>
        <div class="myslider__arrow myslider__right" data-myslider-next='sliderID'>next</div>
      </div>
      <div class="myslider__slider" data-myslider-slider='sliderID'>
        <div class="myslider__slide" data-myslider-slide='sliderID'>1</div>
        <div class="myslider__slide" data-myslider-slide='sliderID'>2</div>
        <div class="myslider__slide" data-myslider-slide='sliderID'>3</div>
        <div class="myslider__slide" data-myslider-slide='sliderID'>4</div>
        <div class="myslider__slide" data-myslider-slide='sliderID'>5</div>
        <div class="myslider__slide" data-myslider-slide='sliderID'>6</div>
        <div class="myslider__slide" data-myslider-slide='sliderID'>7</div>
        <div class="myslider__slide" data-myslider-slide='sliderID'>8</div>
        <div class="myslider__slide" data-myslider-slide='sliderID'>9</div>     
      </div>
      <div class="myslider__dots" data-myslider-dots='sliderID'></div>
    </div>
Enter fullscreen mode Exit fullscreen mode

CSS

[data-myslider-container] {
  width: 100%;
  overflow: hidden;
  position: relative;
}
[data-myslider-slider] {
  display: flex;
  position: relative;
  transition: left 0.5s;
  overflow-x: hidden;
  scroll-behavior: smooth;
  left: 0;
}
Enter fullscreen mode Exit fullscreen mode

JS

class Myslider {
  constructor(selector, settings) {
    this.settings = settings
    this.slidesVisible = settings.slides ?? 1
    this.screen = window.screen.width
    this.$el = document.querySelector(selector) 
    this.sliderID = this.$el.dataset.mysliderContainer
    this.$slider = this.$el.querySelector(`[data-myslider-slider='${this.sliderID}']`)
    this.$next = document.querySelector(`[data-myslider-next='${this.sliderID}']`)
    this.$prev = document.querySelector(`[data-myslider-prev='${this.sliderID}']`)
    this.$dots = document.querySelector(`[data-myslider-dots='${this.sliderID}']`)
    this.dotsItems = null
    this.activeId = 0
    this.slideWIdth =  this.$el.offsetWidth / this.slidesVisible
    this.slides = this.$slider.querySelectorAll(`[data-myslider-slide='${this.sliderID}']`)
    this.slidesCount =  this.slides.length
    this.sectionCount = Math.ceil(this.slidesCount / this.slidesVisible)
    this.position = this.$slider.style.left
    this.responsive = settings.responsive ?? null
    this.sliderInit()
  }


  sliderInit() {
    this.sizeInit()
    if (this.$next && this.$prev) {
      this.arrowsInit()
    }
    if (this.$dots) {
      this.dotsInit()
    }
    if (this.responsive && this.responsive.length > 0) {
      this.responsive.unshift({width: this.screen, slides: this.settings.slides ?? 1})
    }
    this.initSwipe()

    window.addEventListener('resize', () => {
      this.activateSlide(0)
      this.sizeInit()
    })
  }

  arrowsInit() {
    this.$next.addEventListener('click', () => {
      this.activateSlide(this.activeId + 1)
    });

    this.$prev.addEventListener('click', () => {
      this.activateSlide(this.activeId - 1)
    });
  }

  sizeInit() {
    if (this.responsive && this.responsive.length) {
      this.responsive.forEach((size, index) => {
        if (size.width > window.innerWidth) {
          this.screen = size.width
          this.slidesVisible = size.slides
        }
      })
    }

    this.slideWIdth = this.$el.offsetWidth / this.slidesVisible

    let index = 0
    this.$slider.style.width = this.slideWIdth * this.slidesCount + 'px'
    this.slides.forEach($slide => {
      $slide.style.width =  this.slideWIdth + 'px'
      $slide.dataset.mysliderid = index
      index++
    })
  }

  dotsInit() {

    for (let i = 0; i < this.sectionCount; i++) {
      this.$dots.insertAdjacentHTML('beforeend', `<div class="myslider__dots__button" data-mysliderdot="${i * (this.slidesVisible)}" data-myslider-dotid='${this.sliderID}'></div>`)
    }
    const dots = document.querySelectorAll(`[data-myslider-dotid='${this.sliderID}']`)
    dots[0].classList.add('active')

    dots.forEach(el => {
      el.addEventListener('click', (e) => {
        const id = +e.target.dataset.mysliderdot
        if (id < this.slidesCount - (this.slidesVisible - 1)) {
          this.activateSlide(id)

        } else {
          this.activateSlide(this.slidesCount - this.slidesVisible)

        }
      })
    })

    this.dotsItems = dots
  }

  activateDot(dots, id) {
    const activeDot = document.querySelector(`[data-mysliderdot="${id}"][data-myslider-dotid='${this.sliderID}']`)
    if (activeDot) {
      dots.forEach(dot => {
        dot.classList.remove('active')
      })
      activeDot.classList.add('active')
    }
  } 



  activateSlide(n) {
    if (n < 0) {
      this.position = this.slideWIdth * (this.slidesCount - this.slidesVisible)
      this.$slider.style.left = -this.position + 'px'
      this.activeId = this.slidesCount - this.slidesVisible
     } else {
      if (n < this.slidesCount - (this.slidesVisible - 1)) {
        this.position = this.slideWIdth * n
        this.$slider.style.left = -this.position + 'px'
        this.activeId = n
       } else {
        this.$slider.style.left = 0
        this.activeId = 0
       }
     }

     this.activateDot(this.dotsItems, this.activeId)

  }

  initSwipe() {
       let initialX = null;
       let initialY = null;    

       const startTouch = (e) => {
         initialX = e.touches[0].clientX;
         initialY = e.touches[0].clientY;
       };     

       const moveTouch = (e) => {
         if (initialX === null) {
           return;
         } 

         if (initialY === null) {
           return;
         }  

         let currentX = e.touches[0].clientX;
         let currentY = e.touches[0].clientY;    
         let diffX = initialX - currentX;
         let diffY = initialY - currentY;

         if (Math.abs(diffX) > Math.abs(diffY)) {
           if (diffX > 0) {
            this.activateSlide(this.activeId + 1)
           } else {
            this.activateSlide(this.activeId - 1)
           }  
         } 

         initialX = null;
         initialY = null;

         e.preventDefault();
       };

       this.$slider.addEventListener("touchstart", startTouch, false);
       this.$slider.addEventListener("touchmove", moveTouch, false);
  }

}


})
Enter fullscreen mode Exit fullscreen mode

USAGE

const slider = new Myslider("[data-myslider-container='sliderID']", {
  slides: 3,
  responsive: [
    {
      width: 992,
      slides: 2
    },
    {
      width: 480,
      slides: 1
    }
  ]
Enter fullscreen mode Exit fullscreen mode

Image of Datadog

Create and maintain end-to-end frontend tests

Learn best practices on creating frontend tests, testing on-premise apps, integrating tests into your CI/CD pipeline, and using Datadog’s testing tunnel.

Download The Guide

Top comments (0)

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay