JSFiddle - React, Tailwind, and code Playground

by Boba Poshtar

HTML

<div class="slider">
  <div class="item">
    <img src="https://poshtarboba.github.io/fe/tmp/1.png" alt="slide 1">
  </div>
  <div class="item">
    <img src="https://poshtarboba.github.io/fe/tmp/2.png" alt="slide 2">
  </div>
  <div class="item">
    <img src="https://poshtarboba.github.io/fe/tmp/3.png" alt="slide 3">
  </div>
  <div class="item">
    <img src="https://poshtarboba.github.io/fe/tmp/4.png" alt="slide 4">
  </div>
  <div class="item">
    <img src="https://poshtarboba.github.io/fe/tmp/5.png" alt="slide 5">
  </div>
  <div class="item">
    <img src="https://poshtarboba.github.io/fe/tmp/6.png" alt="slide 1">
  </div>
  <div class="item">
    <img src="https://poshtarboba.github.io/fe/tmp/7.png" alt="slide 2">
  </div>
  <div class="item">
    <img src="https://poshtarboba.github.io/fe/tmp/8.png" alt="slide 3">
  </div>
  <div class="item">
    <img src="https://poshtarboba.github.io/fe/tmp/9.png" alt="slide 4">
  </div>
  <span class="prev">&#10094;</span>
  <span class="next">&#10095;</span>
</div>

<div class="slider-dots">
  <span class="slider-dots_item" data-item="0"></span> 
  <span class="slider-dots_item" data-item="1"></span> 
  <span class="slider-dots_item" data-item="2"></span>
</div>

CSS

.slider {
  position: relative;
  margin: 0 auto;
  width: 396px;
  font-size: 0;
  line-height: 0;
  white-space: nowrap;
  border: 2px solid silver;
}
.slider .item {
  position: relative;
  display: inline-block;
  left: 0;
  padding: 2px;
}
.slider .item.active {
  transition: left 500ms;
}
.slider .prev,
.slider .next {
  position: absolute;
  top: 50px;
  z-index: 50;
  font-size: 30px;
  line-height: 30px;
  cursor: pointer;
}
.slider .prev {
  left: 8px;
}
.slider .next {
  right: 8px;
}

.slider-dots {
  padding: 8px 0;
  text-align: center;
}
.slider-dots_item {
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 1px solid silver;
  border-radius: 50%;
  cursor: pointer;
}
.slider-dots_item.active {
  background: silver;
}

JavaScript

(function (){

let slidesForSlide = 3;
let slides = document.querySelectorAll(".slider .item");

// перевірка чи правильна кількість слайдів
if (slides.length === 0) {
	return console.log('Slides not found');
}
if (slides.length % slidesForSlide !==0) {
	return console.log('Count of slides is not a multiple of ' + slidesForSlide);
}

// мета-слайд - пакет з трьох слайдів
let activeMetaSlide = 0;
let metaSlideCount = slides.length / slidesForSlide;

// взнати ширину одного слайда, зберегти у змінну.
let slideWidth = slides[0].offsetWidth;
let sliderWidth = slideWidth * slidesForSlide;

// першим N слайдам дати клас active
for (let i = 0; i < slidesForSlide; i++) {
	slides[i].classList.add("active");
}

// при кліку на стрілку вліво:
document.querySelector(".slider .prev").onclick = function (){
	slideWidth = slides[0].offsetWidth;
	sliderWidth = slideWidth * slidesForSlide;
	// змінюємо мета-слайд на попередній
	activeMetaSlide--;
  if (activeMetaSlide < 0) {
  	activeMetaSlide = metaSlideCount - 1;
  }
	// поточні активні слайди зсовуємо вліво на ширину слайдера
	slides.forEach(function (elem){
  	if (elem.classList.contains('active')) {
      elem.style.left = -sliderWidth + 'px';
    }
  });
  // знаходимо слайди з нового мета-слайда і ставимо їх справа від слайдера
  // добавляємо клас active який посуне їх на центр екрана стилями
  let n = activeMetaSlide * slidesForSlide;
  for (let i = 0; i < slidesForSlide; i++) {
  	slides[n + i].style.left = sliderWidth + 'px';
    slides[n + i].classList.add('active');
  }
};

// при кліку на стрілку вправо:
document.querySelector(".slider .next").onclick = function (){
	slideWidth = slides[0].offsetWidth;
	sliderWidth = slideWidth * slidesForSlide;
	// змінюємо мета-слайд на попередній
	activeMetaSlide++;
  if (activeMetaSlide >= metaSlideCount) {
  	activeMetaSlide = 0;
  }
	// поточні активні слайди зсовуємо вліво на ширину слайдера
	slides.forEach(function (elem){
  	if (elem.classList.contains('active')) {
   ...