Carousel

Native scroll-snap containers without a slider runtime

Carousel

Import

@import "tailwindcss";
@import "@duskmoon-dev/core";

Individual CSS: @duskmoon-dev/core/components/carousel.css (also available via the style export condition on @duskmoon-dev/core/components/carousel). JavaScript import { css, styles } from "@duskmoon-dev/core/components/carousel" exposes CSS text and a nullable CSSStyleSheet (null during SSR). It is not an interaction runtime.

Example

Carousel composition

API And Accessibility

Semantic text variants: carousel-primary, carousel-secondary, carousel-tertiary, carousel-info, carousel-success, carousel-warning, carousel-error. Keep meaningful labels and values; color alone is not an accessible distinction.

Classes: carousel, carousel-item, carousel-horizontal (default), carousel-vertical, carousel-start, carousel-center, carousel-end. Vertical containers are bounded by --carousel-height (24rem default). Items can have different sizes, bounded by the container. Keep the scrollbar available. The focused container supports browser scrolling keys; touch and pointer scrolling are native. Tab reaches nested links and buttons.

Provide a visible heading or accessible label and tabindex="0" on the scroll container. No autoplay or looping is provided. Smooth scrolling becomes immediate under reduced motion. Optional navigation requires an application controller; CSS does not make buttons scroll.

const carousel = document.querySelector(".carousel");
const items = [...carousel.querySelectorAll(".carousel-item")];
const buttons = document.querySelectorAll('[data-carousel-index]');
// Wire each labeled navigation button to its corresponding item.
buttons.forEach((button, index) => button.addEventListener("click", () => {
  items[index].scrollIntoView({ block: "nearest", inline: "start",
    behavior: matchMedia("(prefers-reduced-motion: reduce)").matches ? "instant" : "smooth" });
}));

For the two-item example, place these controls outside the scroll region:

<nav aria-label="Project navigation">
  <button class="btn btn-sm" data-carousel-index="0">Observatory</button>
  <button class="btn btn-sm" data-carousel-index="1">Moon atlas</button>
</nav>