DEV Community

ktr92
ktr92

Posted on

[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

Top comments (0)