Skip to content

Instantly share code, notes, and snippets.

@iankit3
Created February 27, 2024 16:29
Show Gist options
  • Save iankit3/9972f06cbd1f593ce17ae940d53a4cd4 to your computer and use it in GitHub Desktop.
Save iankit3/9972f06cbd1f593ce17ae940d53a4cd4 to your computer and use it in GitHub Desktop.
Vanilla Carousel
<div class="carousel">
<div class="scroller">
<img src="https://img.freepik.com/free-photo/red-white-cat-i-white-studio_155003-13189.jpg">
<img src="https://img.freepik.com/free-photo/closeup-shot-beautiful-ginger-domestic-kitten-sitting-white-surface_181624-35913.jpg">
<img src="https://img.freepik.com/free-photo/closeup-shot-cute-black-kitten-isolated-white_181624-8262.jpg">
</div>
<span class="btn prev">
<svg clip-rule="evenodd" fill="#fff" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="m12.012 2c5.518 0 9.997 4.48 9.997 9.998 0 5.517-4.479 9.997-9.997 9.997s-9.998-4.48-9.998-9.997c0-5.518 4.48-9.998 9.998-9.998zm-1.523 6.21s-1.502 1.505-3.255 3.259c-.147.147-.22.339-.22.531s.073.383.22.53c1.753 1.754 3.254 3.258 3.254 3.258.145.145.335.217.526.217.192-.001.384-.074.531-.221.292-.293.294-.766.003-1.057l-1.977-1.977h6.693c.414 0 .75-.336.75-.75s-.336-.75-.75-.75h-6.693l1.978-1.979c.29-.289.287-.762-.006-1.054-.147-.147-.339-.221-.53-.222-.19 0-.38.071-.524.215z" fill-rule="nonzero" />
</svg>
</span>
<span class="btn next">
<svg clip-rule="evenodd" fill="#fff" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="m12.007 2c-5.518 0-9.998 4.48-9.998 9.998 0 5.517 4.48 9.997 9.998 9.997s9.998-4.48 9.998-9.997c0-5.518-4.48-9.998-9.998-9.998zm1.523 6.21s1.502 1.505 3.255 3.259c.147.147.22.339.22.531s-.073.383-.22.53c-1.753 1.754-3.254 3.258-3.254 3.258-.145.145-.335.217-.526.217-.192-.001-.384-.074-.531-.221-.292-.293-.294-.766-.003-1.057l1.977-1.977h-6.693c-.414 0-.75-.336-.75-.75s.336-.75.75-.75h6.693l-1.978-1.979c-.29-.289-.287-.762.006-1.054.147-.147.339-.221.53-.222.19 0 .38.071.524.215z" fill-rule="nonzero" />
</svg>
</span>
</div>
const carouselContainer = document.querySelector(".carousel > div.scroller");
const prev = document.querySelector(".btn.prev");
const next = document.querySelector(".btn.next");
const config = {
interval: 2000,
size: 350,
autoplay: true,
loop: false
};
// turn loop to true automatically
if (config.autoplay) {
config.loop = true;
}
const { interval, size, autoplay, loop } = config;
if (!loop) {
prev.classList.add("disabled");
}
const DIR = {
right: "right",
left: "left"
};
function move(dir = DIR.right) {
const { scrollWidth, scrollLeft, clientWidth } = carouselContainer;
const total = scrollLeft + clientWidth;
const scrollTo = dir === DIR.right ? 0 : scrollWidth;
const scrollBy = dir === DIR.right ? size : -size;
function removeDisabled() {
prev.classList.remove("disabled");
next.classList.remove("disabled");
}
function handleLoop(elem) {
if (loop) {
carouselContainer.scrollTo(scrollTo, 0);
}
}
removeDisabled();
if (dir === DIR.left) {
// second page
if (!loop && total - size === size) {
prev.classList.add("disabled");
}
if (total === size) {
handleLoop(prev);
} else {
carouselContainer.scrollBy(scrollBy, 0);
}
} else {
// second last page
if (!loop && scrollWidth - total === size) {
next.classList.add("disabled");
}
if (scrollWidth === total) {
handleLoop(next);
} else {
carouselContainer.scrollBy(scrollBy, 0);
}
}
}
const intervalRef = null;
if (autoplay) {
setInterval(() => {
move();
}, interval);
}
prev.addEventListener("click", (ev) => {
if (!ev.currentTarget.classList.contains("disabled")) {
move(DIR.left);
}
});
next.addEventListener("click", (ev) => {
if (!ev.currentTarget.classList.contains("disabled")) {
move(DIR.right);
}
});
document.addEventListener("beforeunload", () => {
clearInterval(intervalRef);
});
.carousel {
margin: auto;
position: relative;
width: 350px;
.scroller {
&::-webkit-scrollbar {
display: none; /* Safari and Chrome */
}
scrollbar-width: none; /* Firefox */
margin: auto;
display: flex;
scroll-snap-type: x mandatory;
overflow: scroll;
background: #222;
img {
scroll-snap-align: center;
width: 100%;
aspect-ratio: 4 / 3;
object-fit: contain;
border: 1px solid;
box-sizing: border-box;
flex: 0 0 350px;
}
}
.btn {
width: 20px;
height: 20px;
position: absolute;
top: 50%;
transform: translateY(-50%);
border-radius: 50%;
background: #000;
&.prev {
left: 0;
}
&.next {
right: 0;
}
&.disabled {
cursor: not-allowed;
background: lightgrey;
}
}
}
@iankit3
Copy link
Author

iankit3 commented Feb 27, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment