JSFiddle - React, Tailwind, and code Playground

by mauricederegt

HTML

<div id="wrap">
      <div class="contents">
          <div class="row nav">
              <div class="slide__wrap">
                  <div class="slide__frame">
                      <div class="slide__img slide__img--1">

                        <div class="grid">
                            <figure class="item">
                                <input type="checkbox" id="1" class="box" />
                                <label for="1">
                                    <img src="https://picsum.photos/seed/100/100" />
                                    <figcaption>Text below the image1</figcaption>
                                </label>
                            </figure>
                           <figure class="item">
                                <input type="checkbox" id="2" class="box" />
                                <label for="2">
                                    <img src="https://picsum.photos/seed/100/100" />
                                    <figcaption>Text below the image1</figcaption>
                                </label>
                            </figure>
                            <figure class="item">
                                <input type="checkbox" id="3" class="box" />
                                <label for="3">
                                    <img src="https://picsum.photos/seed/100/100" />
                                    <figcaption>Text below the image1</figcaption>
                                </label>
                            </figure>
                            <figure class="item">
                                <input type="checkbox" id="4" class="box" />
                                <label for="4">
                                    <img src="https://picsum.photos/seed/100/100" />
                                    <figcaption>Text below the image1</figcaption>
                                </label>
                            </figure>
                            <figure...

CSS

body {
  margin: 0; /* This is used to reset any browser-default margins */
  padding: 0; /* This is used to reset any browser-default margins */
  overflow: hidden; /* Hide scrollbars */
  background: #fff;
  -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
.contents {
}
#contents__header {
  height: 20vh;
}
.contents__footer {
  height: 20vh;
  background: #f1f1f1;
}

.slide__wrap {
  display: inline-flex;
  transform: translateX(0);
  will-change: transform;
  transition: transform 0.3s ease-out;
  cursor: grab;
  background: black;
  height: 100%;
}
.slide__frame {
  max-height: 100vh;
  width: 100vw;
  display: flex;
  align-items: center;
  justify-content: center;
}
.slide__img {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.2s ease-in-out;
}
.slide__img--1 {
  background-color: #fff;
}
.slide__img--2 {
  background-color: #fffF;
}
.slide__img--3 {
  background-color: #fff;
}
.grabbing {
  cursor: grabbing;
}
.dot__wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  font-size: 0;
  margin-left: -20px; /* new; to counter 10px +spacing margin-left dots */
}
.dot__item {
  width: 10px;
  height: 10px;
  background-color: #A1A1A1;
  border-radius: 50%;
}
.dot__item + .dot__item {
  margin-left: 10px;
}
.dot__item.is-active {
  background-color: #023047;
}

/* @media (min-width: 600px) { */
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  gap: 2%;
  padding: 1%;
}
/* } */

figure.item {
   border: 1px solid #000;
    /* To horizontally center images and caption */
    text-align: center;
    margin: 0;
  padding: 0;
}
/* hack to make images flexible: width: 100%;*/
img {
    width: 100%;
}
.caption {
    /* visibility: hidden; */
}

img,...

JavaScript

const slider = document.querySelector('.slide__wrap'),
        slides = Array.from(document.querySelectorAll('.slide__frame')),
        slideLength = slides.length,
        dotWrap = document.querySelector('.dot__wrap'),
        active = 'is-active';

    let isDragging = false,
        startPos = 0,
        currentTranslate = 0,
        prevTranslate = 0,
        animationID,
        currentIndex = 0;

    slides.forEach((slide, index) => {
        const slideImage = slide.querySelector('.slide__img')
        // disable default image drag
        slideImage.addEventListener('dragstart', (e) => e.preventDefault())
        // touch events
        slide.addEventListener('touchstart', touchStart(index))
        slide.addEventListener('touchend', touchEnd)
        slide.addEventListener('touchmove', touchMove)
        // mouse events
        slide.addEventListener('mousedown', touchStart(index))
        slide.addEventListener('mouseup', touchEnd)
        slide.addEventListener('mousemove', touchMove)
        slide.addEventListener('mouseleave', touchEnd)
    })

    // make responsive to viewport changes
    window.addEventListener('resize', setPositionByIndex)

    // prevent menu popup on long press
    window.oncontextmenu = function (event) {
        event.preventDefault()
        event.stopPropagation()
        return false
    }

    createIndicator();

    function getPositionX(event) {
        return event.type.includes('mouse') ? event.pageX : event.touches[0].clientX
    }

    function touchStart(index) {
        return function (event) {
            currentIndex = index
            startPos = getPositionX(event)
            isDragging = true
            animationID = requestAnimationFrame(animation)
            slider.classList.add('grabbing')
        }
    }

    function touchMove(event) {
        if (isDragging) {
            const currentPosition = getPositionX(event)
            currentTranslate = prevTranslate + currentPosition - startPos
        }
...