<!-- for article: https://utilitybend.com/blog/love-at-first-slide-creating-a-carousel-purely-out-of-css -->
<div class="carousel">
<div>
<img src='https://images.unsplash.com/photo-1735437643865-18e22575a630?crop=entropy&cs=srgb&fm=jpg&ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3MzgyNTUzODd8&ixlib=rb-4.0.3&q=85' alt=''>
</div>
<div>
<img src='https://images.unsplash.com/photo-1736604925910-a6ebc20ed892?crop=entropy&cs=srgb&fm=jpg&ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3MzgyNTUzODd8&ixlib=rb-4.0.3&q=85' alt=''>
</div>
<div>
<img src='https://images.unsplash.com/photo-1732452792160-c28abdcd4b64?crop=entropy&cs=srgb&fm=jpg&ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3MzgyNTU0NDV8&ixlib=rb-4.0.3&q=85' alt=''>
</div>
</div>
<!-- for demo purpose -->
<div class="warning">This is an experimental demo for scroll markers made in Chrome Canary, Your browser does not support scroll markers</div>
@layer base, carouselAndMarkers, carouselArrows;
@layer carouselAndMarkers {
.carousel {
display: grid;
grid-auto-columns: 100%;
grid-auto-flow: column;
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
scrollbar-width: none;
max-inline-size: 1200px;
margin: 0 auto;
scroll-behavior: smooth;
scroll-marker-group: after;
&::scroll-marker-group {
width: 100%;
display: flex;
gap: 12px;
align-items: center;
padding: 20px 0;
justify-content: center;
z-index: 20;
}
div {
scroll-snap-stop: always;
scroll-snap-align: start;
&::scroll-marker {
display: block;
content: " ";
aspect-ratio: 1;
width: 24px;
border-radius: 50%;
border: 1px solid silver;
cursor: pointer;
background: transparent;
justify-content: center;
transition: background 0.5s ease-out;
}
&::scroll-marker:target-current {
background: white;
}
&::scroll-marker:where(:hover, :active, :focus) {
background: lightgray;
}
}
img {
width: 100%;
aspect-ratio: 16/9;
object-fit: cover;
}
}
}
@layer carouselArrows {
.carousel {
anchor-name: --carousel;
&::scroll-button(inline-end),
&::scroll-button(inline-start) {
z-index: 1;
cursor: pointer;
position: absolute;
position-anchor: --carousel;
top: anchor(center);
inset-inline: anchor(start) anchor(end);
inline-size: 44px;
aspect-ratio: 1;
backdrop-filter: blur(5px);
border: 1px solid silver;
border-radius: 50%;
line-height: 1;
content: "";
background-color: rgb(255 255 255 / 0.5);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='currentColor' class='size-6'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M15.75 19.5 8.25 12l7.5-7.5' /%3E%3C/svg%3E%0A");
background-size: 24px 24px;
background-repeat: no-repeat;
background-position: center;
translate: 20px -50%;
transition: background-color 0.5s ease-out;
}
&::scroll-button(inline-end) {
top: anchor(center);
inset-inline: auto anchor(end);
content: "";
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='currentColor' class='size-6'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='m8.25 4.5 7.5 7.5-7.5 7.5' /%3E%3C/svg%3E%0A");
translate: -20px -50%;
}
&::scroll-button(inline-end):where(:hover, :focus, :active),
&::scroll-button(inline-start):where(:hover, :focus, :active) {
background-color: rgb(255 255 255);
}
}
}
@layer base {
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
background: linear-gradient(#555, #222);
min-height: 100dvh;
margin: 0;
padding: 5vmin;
}
}
.warning {
background: #ffd503;
font-family: Helvetica, Arial, sans-serif;
position: fixed;
top: 20px;
left: 20px;
padding: 20px;
max-width: 500px;
border-radius: 5px;
z-index: 100;
}
@supports (scroll-marker-group: after) {
.warning {
display: none;
}
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.