<div class="carousel__wrapper">
<!-- Left button -->
<button class="carousel__button carousel__button--left">
<svg aria-hidden="true" stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 512 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
<path d="M256 504C119 504 8 393 8 256S119 8 256 8s248 111 248 248-111 248-248 248zM142.1 273l135.5 135.5c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L226.9 256l101.6-101.6c9.4-9.4 9.4-24.6 0-33.9l-17-17c-9.4-9.4-24.6-9.4-33.9 0L142.1 239c-9.4 9.4-9.4 24.6 0 34z"></path>
</svg>
</button>
<!-- Right button -->
<button class="carousel__button carousel__button--right">
<svg aria-hidden="true" stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 512 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
<path d="M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zm113.9 231L234.4 103.5c-9.4-9.4-24.6-9.4-33.9 0l-17 17c-9.4 9.4-9.4 24.6 0 33.9L285.1 256 183.5 357.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L369.9 273c9.4-9.4 9.4-24.6 0-34z"></path>
</svg>
</button>
<div class="carousel__scroll-area">
<!-- Placeholder images to work with -->
<figure>
<img src="https://picsum.photos/853/480?random=1" alt="" width="853" height="480">
<figcaption>
Place image caption here
</figcaption>
</figure>
<figure>
<img src="https://picsum.photos/853/480?random=2" alt="" width="853" height="480">
<figcaption>
Place image caption here
</figcaption>
</figure>
<figure>
<img src="https://picsum.photos/853/480?random=3" alt="" width="853" height="480" objectFit="cover" />
<figcaption>
Place image caption here
</figcaption>
</figure>
<figure>
<img src="https://picsum.photos/853/480?random=4" alt="" width="853" height="480" objectFit="cover" />
<figcaption>
Place image caption here
</figcaption>
</figure>
<figure>
<img src="https://picsum.photos/853/480?random=5" alt="" width="853" height="480">
<figcaption>
Place image caption here
</figcaption>
</figure>
<!-- End of placeholder images -->
</div>
</div>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: system-ui, sans-serif;
}
html {
height: 100%;
}
body {
display: grid;
place-items: center;
min-height: 90%;
}
.carousel__wrapper {
max-width: min(80%, 853px);
/* So we can absolutely position our buttons on top of the carousel */
position: relative;
}
.carousel__scroll-area {
display: flex;
overflow-x: scroll;
max-width: 100%;
aspect-ratio: 16 / 9;
/* enforces children snapping on the x axis */
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
}
figure {
/* makes sure images always snap in turn */
scroll-snap-align: start;
scroll-snap-stop: always;
/* So will can absolutely position our figcaption */
position: relative;
/* Makes sure each image covers the scroll window */
max-width: 100%;
flex-shrink: 0;
}
img {
/* Make sure the images never get too large */
max-width: 100%;
max-height: 100%;
}
figcaption {
position: absolute;
left: 0;
right: 0;
bottom: 0;
padding: 0.5rem;
font-style: italic;
text-align: center;
color: white;
/* To make our white caption a little more legible on the image */
background-image: linear-gradient(to top, rgb(0 0 0 / 0.5), transparent);
}
.carousel__button {
position: absolute;
top: 0;
bottom: 0;
z-index: 1;
background: none;
border: none;
padding: 2rem 1rem;
color: white;
}
.carousel__button--left {
left: 0;
}
.carousel__button--right {
right: 0;
}
// We first grab our scroll area and carousel buttons
const carouselScrollArea = document.querySelector(".carousel__scroll-area");
const leftCarouselButton = document.querySelector(".carousel__button--left");
const rightCarouselButton = document.querySelector(".carousel__button--right");
// We then listen in for clicks and scroll the carousel accordingly
leftCarouselButton.addEventListener("click", () => scrollCarousel("left"));
rightCarouselButton.addEventListener("click", () => scrollCarousel("right"));
function scrollCarousel(direction) {
if (direction === "left") {
carouselScrollArea.scrollLeft -= carouselScrollArea.clientWidth;
} else if (direction === "right") {
carouselScrollArea.scrollLeft += carouselScrollArea.clientWidth;
} else {
console.error("Invalid direction");
}
}
// We grab the whole carousel wrapper
const carouselWrapper = document.querySelector(".carousel__wrapper");
// We listen for keypresses and react based on which key was pressed
carouselWrapper.addEventListener("keydown", handleKeyDown);
function handleKeyDown(e) {
if (event.key === "ArrowLeft") {
scrollCarousel("left");
} else if (event.key === "ArrowRight") {
scrollCarousel("right");
}
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.