> For the complete documentation index, see [llms.txt](https://analog.groupthought.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://analog.groupthought.com/reference/alpine/carousel.md).

# x-carousel

Mouse-drag panning with momentum for horizontal scrollers, landing on CSS scroll-snap points.

Mouse-drag panning with momentum for horizontal scrollers, landing on CSS scroll-snap points.

| Directive / magic                     | What it does                                                                                                                                                                                                                                        |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-carousel`                          | The root. Holds the pan state (`role="region"`, `aria-roledescription="carousel"`)                                                                                                                                                                  |
| `x-carousel:viewport`                 | The visible area. Watches pan gestures and resizes. Uses the `$id('carousel')` id                                                                                                                                                                   |
| `x-carousel:track`                    | The scrollable row that holds the slides                                                                                                                                                                                                            |
| `x-carousel:track.autoregister`       | Also registers every child of the track as a slide, and keeps up when children are added or removed                                                                                                                                                 |
| `x-carousel:item`                     | Registers one element as a slide (`role="group"`, `aria-roledescription="slide"`)                                                                                                                                                                   |
| `x-carousel:prev` / `x-carousel:next` | Buttons that page the list backward / forward                                                                                                                                                                                                       |
| `$carousel`                           | The state, readable anywhere inside the root: `state` (`'initial'`, `'panning'`, `'animating'`, `'scrolling'`), `isPanning`, `isEnabled`, `items`, `visibleIndices`, `centeredIndex`, `isScrolling`, `scrollTo(index, options)`, `next()`, `prev()` |

Touch devices use native scrolling. Mouse devices use the pan gesture. Slides block `dragstart` so images and links don't interfere with panning. After a drag, a spring moves the track to the nearest CSS scroll-snap point. Add scroll-snap classes such as `snap-x snap-mandatory` to the track. RTL pages need no separate configuration.

## Examples

### A basic carousel

Use `x-carousel:track.autoregister` to make every child of the track a slide:

```html
<div x-carousel>
  <div x-carousel:viewport class="overflow-clip">
    <div x-carousel:track.autoregister class="flex gap-layout snap-x snap-mandatory">
      <div class="snap-start">First card</div>
      <div class="snap-start">Second card</div>
    </div>
  </div>
</div>
```

The `core-card-slider` snippet renders this structure for every card slider in the theme. Without `.autoregister`, mark each slide yourself with `x-carousel:item`.

### Prev and next buttons

Use `x-carousel:prev` and `x-carousel:next` to page the list:

```html
<button x-carousel:prev aria-label="Previous">…</button>
<button x-carousel:next aria-label="Next">…</button>
```

The theme's `showcase-controls` snippet pairs these with the `x-overflow` plugin, so each button disables at its end of the track (`:disabled="!$overflow.start"`).

### Position indicators

Use `$carousel.items.length` and `$carousel.centeredIndex` to draw pagination dots:

```html
<div x-show="$carousel.items.length > 1">
  <template x-for="(_, index) in $carousel.items.length">
    <button
      :class="{ 'opacity-100': $carousel.centeredIndex == index }"
      :aria-label="index + 1"
      @click="$carousel.scrollTo(index)"
    ></button>
  </template>
</div>
```

Setting `$carousel.centeredIndex` scrolls to that slide. `scrollTo` also takes an options object with `align: 'start' | 'center' | 'end'`.

### Hiding controls when nothing scrolls

Use `$carousel.isEnabled` to hide controls while the track fits inside the viewport:

```html
<div :class="{ 'opacity-0': $carousel.isEnabled == false }">…</div>
```

`isEnabled` is true only when the track is wider than the viewport.

## Options

`x-carousel` takes no options object. The scroll positions a drag can land on come from the CSS scroll-snap classes on the track and its slides. Slides that contain lazy-loaded images may need `transform: translate3d(0,0,0)` to stay smooth while panning.
