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
}
...