CSS-Only Carousels -- ::scroll-button and ::scroll-marker

Carousels. Love them or hate them, they're everywhere. And for years, building an accessible carousel meant pulling in a JavaScript library, managing scroll state, and hoping for the best. Sound familiar?

CSS now has ::scroll-button() and ::scroll-marker pseudo-elements for fully functional carousels with zero JavaScript. Chrome 135+ stable.

Navigation Buttons

.carousel {
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
}

.carousel::scroll-button(left) {
  content: '<';
}

.carousel::scroll-button(right) {
  content: '>';
}

Pagination Dots

.carousel::scroll-marker-group {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
}

.carousel > *::scroll-marker {
  content: '';
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #ccc;
}

.carousel > *::scroll-marker:target-current {
  background: #333;
}

Why This Is Huge

  • Zero JavaScript -- browser handles all scroll logic
  • Accessible by default -- keyboard and screen reader support
  • Buttons auto-disable at scroll boundaries
  • Pagination dots track current position automatically

Browser Support

Chrome/Edge 135+ (stable). Firefox and Safari in progress. Part of Interop 2026.

Here's the thing -- this isn't just nice-to-have. The browser is doing what we've asked JavaScript libraries to do for over a decade.

• • •

Happy coding!

If you want to go deeper and learn how to build real, production-ready CSS design systems step by step, check out my full course here: CSS Design Systems Course If you found this helpful, I'd love to connect! Follow me on Twitter/X @alexandersstudi or LinkedIn for more CSS and design system tips.