Malevich

Blocks/

Carousel

scroll-snap track with prev/next + pagination dots.

Carousel

Horizontal slide track with native scroll-snap. Per the answered design question recorded with this component: minimal scope — scroll-snap, prev/next buttons, pagination dots. No autoplay, no loop, no fade in v1.0 (deferred to v1.1).

When to use

If the content is a long list with arbitrary scroll, prefer a regular horizontally-scrolling container without the carousel chrome.

Anatomy

<section class="carousel" aria-roledescription="carousel">
  <div class="carousel__viewport">
    <div class="carousel__track" tabindex="0" aria-label="Slides">
      <article class="carousel__slide" aria-roledescription="slide" aria-label="1 of 3">…</article>
      <article class="carousel__slide" aria-roledescription="slide" aria-label="2 of 3">…</article>
      <article class="carousel__slide" aria-roledescription="slide" aria-label="3 of 3">…</article>
    </div>
  </div>

  <div class="carousel__controls">
    <button type="button" class="carousel__prev" aria-label="Previous slide">‹</button>
    <ol class="carousel__dots" role="tablist" aria-label="Slide navigation">
      <li><button type="button" class="carousel__dot" aria-selected="true"  aria-label="Go to slide 1"></button></li>
      <li><button type="button" class="carousel__dot" aria-selected="false" aria-label="Go to slide 2"></button></li>
      <li><button type="button" class="carousel__dot" aria-selected="false" aria-label="Go to slide 3"></button></li>
    </ol>
    <button type="button" class="carousel__next" aria-label="Next slide">›</button>
  </div>
</section>

The runtime (initCarousel, auto-registered for .carousel) syncs aria-selected on dots and disabled on prev/next buttons in response to scroll position. Clicking prev/next/dot triggers a smooth scroll on the track.

The native scroll-snap and overflow-x give touch swipe, mouse drag (on supporting browsers), and keyboard scroll for free when the track has tabindex="0".

Tokens used

From semantic tier

Component-tier (generated)

Accessibility

For full keyboard navigation (Left/Right arrows step slides programmatically), pair with a small inline script — the runtime does not bind keyboard events itself (browsers already handle arrow-key scrolling on the focused track).

Edge cases

Do

Don't