Skip to main content

Carousel

Info:Media
23

A scroll-snap track of slides with prev/next controls, dots, keyboard, and opt-in autoplay.

slideshow gallery slides swiper scroll snap slider

Live demo

live · @xtyle/astro

Carousel

Image gallery

With controls="overlay" the prev/next arrows ride the slide edges and the dots float over the bottom, for an in-image gallery. The overlay is click-through except for the controls.

Dawn over the ridge
Violet dusk
Sea glass
Ember
Nightfall

Hover previews in a carousel

Each slide is an Image carrying its own preview, and each one is a different kind: a hover-src video, a nested carousel, and a moving image. Hovering (or focusing) a slide reveals its preview and pauses the outer carousel's autoplay in the same gesture; leaving resets both.

Dawn over the ridge
Sea glass
Ember

Autoplay and loop

Advances every 4s and loops seamlessly at the ends (no rewind), pausing when you hover or focus it.

Highlight 1
Highlight 2
Highlight 3
Highlight 4
Highlight 5

Fade, scale, and flip transitions

transition stacks the slides and cross-fades the active one instead of paging a track: fade dissolves, scale adds a zoom, flip turns the card. Each auto-advances so you can watch the motion.

fade

1
2
3
4
5

scale

1
2
3
4
5

flip

1
2
3
4
5

Direction: vertical and reversed

direction sets the axis and sense: up / down page a vertical track (give it a height with --carousel-height), and left advances a horizontal track in reverse.

down (vertical)

Dawn over the ridge
Violet dusk
Sea glass
Ember
Nightfall

left (reversed)

Highlight 1
Highlight 2
Highlight 3
Highlight 4
Highlight 5

Content slides

“Ships beautifully out of the box.”

“The theming just works.”

“Every slide stays on-brand.”

Carousel lays its slotted children out as a horizontal scroll-snap track: each child is a slide, and the browser's own scrolling does the paging, so the track is swipeable and keyboard-scrollable with no JavaScript at all. When the runtime is present it grows a control bar, prev and next buttons (drawn with the chevron icons), a row of pagination dots that track and drive the active slide, and arrow-key and Home/End navigation, all wired over the same native scroll.

An opt-in autoplay advances the track on an interval, pausing on hover and focus and standing still entirely under prefers-reduced-motion; loop wraps the ends seamlessly, scrolling into an inert clone of the far slide and then silently snapping to the real one so the wrap never rewinds. The transition prop swaps the paging model: slide keeps the scroll-snap track, while fade, scale, and flip stack the slides and cross-fade the active one, so a testimonial or hero rotator can dissolve rather than slide. It is content-agnostic: the slides can be Images, Cards, or any markup, and it exposes itself as a labelled carousel region with each slide named for assistive tech.

When to use

How this component composes with the rest of the set.

Put Images in the track for a photo gallery; pair each with a ratio so the slides stay a consistent height.
Slot Cards for a featured-content rail, or any markup for a testimonial or onboarding sequence.
Set autoplay with loop for an unattended hero rotation; it pauses the moment a user hovers or focuses it.
Set controls="false" on a touch-first surface to lean on swipe and dots alone.
A vertical direction (up / down) suits uniform, media-shaped slides: it pins each slide to --carousel-height and clips the overflow, so give it a height that fits the content and reach for it over long text cards.

Props

9 props, straight from the manifest.

PropTypeDefaultBindingsDescription
label string
html svelte astro
The accessible name for the carousel region. Always set it so assistive tech can announce the carousel.
autoplay boolean false
html svelte astro
Auto-advances the track on the `interval`. Pauses on hover and focus, and never runs under reduced-motion.
interval number 5000
html svelte astro
The autoplay dwell per slide, in milliseconds.
loop boolean false
html svelte astro
Wraps seamlessly past the last slide to the first (and back): the track scrolls forward into an inert clone of the far slide, then silently snaps to the real one, so the wrap reads as continuous motion instead of a rewind. The prev/next buttons stay enabled at the ends.
controls boolean | "overlay"
true false overlay
true
html svelte astro
Where the prev/next buttons sit: `true` renders them in a bar below the track; `"overlay"` floats them on the slide edges (arrows at the left/right, dots and the play toggle over the bottom) for an in-image gallery; `"false"` hides them and relies on swipe, dots, and keys. The overlay layer is click-through except for the controls, so a swipe or a link inside a slide still works.
dots boolean true
html svelte astro
Shows the pagination dots. Set `dots="false"` to hide them.
pause-on-hover boolean true
html svelte astro
Whether hovering or focusing the carousel pauses autoplay. Set `pause-on-hover="false"` when the rotation is the point and should keep running under the pointer: a decorative marquee, an ambient gallery, or a preview revealed inside an `Image`'s `hover` slot (which only shows while hovered, so a hover-pause would freeze it on its first slide). The explicit play/pause toggle and `prefers-reduced-motion` still stop it, so the content stays pausable.
transition CarouselTransition
slide fade scale flip
slide
html svelte astro
How slides change. `slide` (the default) pages a scroll-snap track sideways; `fade`, `scale`, and `flip` instead stack the slides and cross-fade the active one (`scale` adds a subtle zoom, `flip` a card turn). The stacked modes have no swipe track, so they lean on the controls, dots, and keys.
direction CarouselDirection
right left up down
right
html svelte astro
Which way a `slide` carousel advances. `right` (the default) and `left` page a horizontal track; `up` and `down` a vertical one (give it a height with `--carousel-height`, default `18rem`). `left` and `up` reverse the sense. Moot for the stacked transitions.

Anatomy

The named parts that make up the component, with their selectors.

track

.xtyle-carousel__track

The horizontal scroll-snap container that holds and pages the slides.

--space-3

nav

.xtyle-carousel__nav

The prev/next buttons.

--bg-1 --fg-1 --line-2 --radius-full

dots

.xtyle-carousel__dot

The pagination dots; the active one takes the accent. When the theme's --selection-cue resolves to marker, the active dot also elongates into a pill so the current slide reads by shape, not color alone.

--bg-3 --accent --selection-cue

Tokens & coverage

What the component consumes, checked live against what the algorithm produces.

Success:fully covered 23/23 consumed tokens produced default register: 299 tokens

Live coverage check against the xtyle-default register (derive(xtyleDefault, { anchors })coverComponent(manifest, register)). Every token this component consumes must be a key the algorithm produces.

--accent --bg-1 --bg-2 --bg-3 --border-thick --border-thin --duration-fast --duration-slow --ease-emphasized --ease-standard --elevation-2 --fg-1 --fg-2 --fg-3 --line-2 --radius-full --ring --selection-cue --space-2 --space-3 --space-6 --surface-overlay --surface-overlay-border

Slots

default
html svelte astro

The slides. Each direct child becomes one slide in the track (an Image, a Card, or any markup).

Accessibility

The carousel is a labelled region with aria-roledescription="carousel", and each slide is a labelled group announced as N of M.
The track is focusable and scrolls with the arrow keys and Home/End; the prev/next buttons and dots are labelled controls.
Autoplay pauses on hover and focus, and stops entirely under prefers-reduced-motion, so motion never runs against a user's stated preference.
An autoplay carousel grows a persistent play/pause toggle in the control bar (WCAG 2.2.2): the user can stop the motion outright, and a deliberate pause survives a pointer leaving and re-entering, unlike the transient hover pause.
The active slide is announced through a polite live region (Slide N of M), so a screen-reader user hears each change even though scrolling, or a stacked cross-fade, never moves focus.
With no JavaScript the slides remain visible and the track stays natively scrollable, so no content is trapped behind the enhancement.
The current slide carries a non-color channel on demand: when the theme sets --selection-cue: marker, the active dot elongates into a pill alongside the accent color, so which slide is current never rests on color alone (WCAG 1.4.1). High-contrast emits marker by default, and any algorithm can opt in via the cues knob.

Code

Image gallery

A few slides in a scroll-snap track with prev/next controls and dots.

<xtyle-carousel label="Product photos">
	<img src="/a.jpg" alt="Front" />
	<img src="/b.jpg" alt="Side" />
	<img src="/c.jpg" alt="Back" />
</xtyle-carousel>
<script lang="ts">
	import { Carousel } from "@xtyle/svelte";
</script>

<Carousel label="Product photos">
	<img src="/a.jpg" alt="Front" />
	<img src="/b.jpg" alt="Side" />
</Carousel>
---
import Carousel from "@xtyle/astro/Carousel.astro";
import Image from "@xtyle/astro/Image.astro";
---

<Carousel label="Gallery">
	<Image src="/a.jpg" alt="First" ratio="16/9" />
	<Image src="/b.jpg" alt="Second" ratio="16/9" />
</Carousel>

Autoplay and loop

An auto-advancing, looping track that pauses on hover or focus.

<xtyle-carousel label="Highlights" autoplay interval="4000" loop>
	<div>Slide one</div>
	<div>Slide two</div>
	<div>Slide three</div>
</xtyle-carousel>
<script lang="ts">
	import { Carousel } from "@xtyle/svelte";
</script>

<Carousel label="Highlights" autoplay interval={4000} loop>
	<div>Slide one</div>
	<div>Slide two</div>
</Carousel>
---
import Carousel from "@xtyle/astro/Carousel.astro";
---

<Carousel label="Highlights" autoplay interval={4000} loop>
	<div>Slide one</div>
	<div>Slide two</div>
</Carousel>

Fade transition

A stacked cross-fade instead of a sliding track, for a testimonial or hero rotator.

<xtyle-carousel label="Featured" transition="fade" autoplay loop>
	<div>First</div>
	<div>Second</div>
	<div>Third</div>
</xtyle-carousel>
<Carousel label="Featured" transition="fade" autoplay loop>
	<div>First</div>
	<div>Second</div>
	<div>Third</div>
</Carousel>
<Carousel label="Featured" transition="fade" autoplay loop>
	<div>First</div>
	<div>Second</div>
	<div>Third</div>
</Carousel>