HyCarousel
Usage examples on this page are written for Lit / plain HTML (
<hy-carousel>). The same component ships asHyCarouselin@whitespaceux/harmony-react(native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.
A native-first carousel built on CSS scroll-snap. Each direct child of <hy-carousel> is treated as a slide. The component renders a Lit baseline navigation and pagination UI so it works cross-browser, and progressively enhances to ::scroll-button / ::scroll-marker pseudo-elements where supported (Chromium 135+, via @supports in the styles).
Rendering model
- Viewport is a flex scrollport with
scroll-snap-type. Slides are direct children of the host, slotted into the shadow-DOM scrollport. - Active slide tracking uses
IntersectionObserverrooted on the viewport withthreshold: 0.5. - Keyboard works from the viewport (
tabindex="0"): Arrow keys, Home/End, PageUp/PageDown. - Autoplay pauses on pointer enter, focus, and hidden tabs, and is disabled entirely when
prefers-reduced-motion: reducematches.
Examples
Basic horizontal carousel
<hy-carousel navigation pagination label="Featured products">
<article>Slide 1</article>
<article>Slide 2</article>
<article>Slide 3</article>
</hy-carousel>API
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
navigation | navigation | boolean | false | Render baseline Previous/Next buttons inside the viewport. |
pagination | pagination | boolean | false | Render baseline pagination markers below the viewport. |
orientation | orientation | 'horizontal' | 'vertical' | 'horizontal' | Scroll axis. |
snap | snap | 'mandatory' | 'proximity' | 'mandatory' | mandatory snaps the scrollport strictly; proximity enables a peek. |
autoplay | autoplay | boolean | false | Advance the active slide on a timer. Disabled automatically when prefers-reduced-motion. |
autoplayInterval | autoplay-interval | number | 5000 | Milliseconds between autoplay advances. |
label | label | string | '' | Accessible label for the carousel region. Required for a meaningful a11y label. |
Events
| Event | Detail | Description |
|---|---|---|
change | — | Fires when the active slide changes (scroll settles past 50% threshold). Detail: { index, slide }. |
input | — | Fires during drag when the active slide crosses the threshold. May fire multiple times per gesture. Detail: { index, slide }. |
Slots
| Slot | Description |
|---|---|
default | Slides — each direct child is treated as one slide. |
CSS Parts
| Part | Description |
|---|---|
base | The carousel's outer wrapper. |
viewport | The scrollport element that overflows. |
navigation | The navigation button group (baseline path). |
navigation-prev | The previous button. |
navigation-next | The next button. |
pagination | The pagination marker group. |
marker | An individual pagination marker. |
CSS Custom Properties
| Property | Description |
|---|---|
--hy-carousel-viewport-padding | Inner padding of the scrollport. Default: 0. |
--hy-carousel-gap | Gap between slides. Default: var(--hy-gap-container-md). |
--hy-carousel-ornament | Marker dot size. Default: var(--hy-ornament-bullet). |
--hy-carousel-marker-color-rest | Marker rest color. Default: var(--hy-border-subtle-rest). |
--hy-carousel-marker-color-active | Active marker color. Default: var(--hy-background-brand-rest). |
--hy-carousel-nav-size | Nav button diameter. Default: var(--hy-touch-target-small). |
--hy-carousel-nav-background | Nav button background. Default: var(--hy-background-surface-base). |
--hy-carousel-nav-color | Nav button foreground. Default: var(--hy-foreground-default-rest). |
--hy-carousel-aspect-ratio | Aspect ratio of the viewport. Default: auto. |
--hy-carousel-hover-duration | Transition duration for hover and focus state feedback on controls |
--hy-carousel-hover-easing | Transition easing for hover and focus state feedback on controls |
Methods
goTo()
Scrolls to the slide at the given index.
next()
Advances to the next slide, stopping at the end.
prev()
Goes to the previous slide, stopping at the start.