<!--
Source: https://www.theui.dev/docs/slider
Part of the theui-svelte documentation. Index: https://www.theui.dev/llms.txt
-->

# Slider

Show images or any content one slide at a time, or several at once, with smooth effects, swipe, keyboard support and accessible controls.

## About

The Slider shows a set of slides one after another. Each slide is a `Slide` component that holds an image or any content. The Slider can play by itself, loop, follow a swipe or a mouse drag, show several slides at once, and change slides with effects like fade, zoom, flip and cube. It works in right-to-left pages and respects the user's reduced motion setting.

## Example

Put `Slide` components inside a `Slider`. By default the Slider plays by itself and shows arrows, dots, a timer bar and a pause button.

### Image Slider

Give a `Slide` an image with `src` and `alt`.

```html
<Slider>
  <Slide src="..." alt="..." />
  <Slide src="..." alt="..." />
  <Slide src="..." alt="..." />
</Slider>
```

### Custom Content Slider

A `Slide` can hold any content instead of an image. Use `class` to style the slide itself.

```html
<Slider>
  <Slide class="h-72 flex-col gap-2 bg-yellow-200">
    <h3>Build Faster</h3>
    <p>...</p>
  </Slide>
  <Slide class="h-72 flex-col gap-2 bg-rose-200"> ... </Slide>
  <Slide class="h-72 flex-col gap-2 bg-teal-200"> ... </Slide>
</Slider>
```

### Linked Slides

Add `href` to make the whole slide a link. The link is named by the image `alt` or by the slide content, so write an `alt` that describes where it goes. A drag or swipe never follows the link. Don't put other links or buttons inside a linked slide.

```html
<Slider>
  <Slide href="/summer" src="..." alt="Shop the summer collection" />
  <Slide href="/new" src="..." alt="See the new arrivals" />
</Slider>
```

## Controls & Indicator

The `controls` prop shows the previous and next buttons, and the `indicator` prop shows a dot for each slide. Both are `true` by default; set them to `false` to hide them. When the slider doesn't loop, the previous button is disabled on the first slide and the next button on the last.

```html
<Slider indicator={false} controls={false}> ... </Slider>
```

Without controls, users can still change slides by swiping or with the keyboard.

## Custom Controls Icon

Replace the arrow icons of the previous and next buttons with the `prevButton` and `nextButton` snippets. The buttons keep their accessible names.

```html
<Slider>
  <!-- Previous button -->
  {#snippet prevButton()}
    <Svg size={2} class="opacity-50">
      <path fill-rule="evenodd" d="M1 8a7 7 0 1 ... 1 .708.708L5.707 7.5z"/>
    </Svg>
  {/snippet}
  <!-- Next button -->
  {#snippet nextButton()}
    <Svg size={2} class="opacity-50">
      <path fill-rule="evenodd" d="M1 8a7 7 0 1 ... 1 0-.708.708L10.293 7.5z"/>
    </Svg>
  {/snippet}

  <Slide src="..." alt="..." />
  <Slide src="..." alt="..." />
  <Slide src="..." alt="..." />
</Slider>
```

## Auto Play & Stop on Hover

The `autoPlay` prop moves to the next slide by itself. It is `true` by default. At the last slide of a slider that doesn't loop, it goes back to the first slide.

Auto play pauses while the mouse is over the slider and continues from where it stopped when the mouse leaves. Set `stopOnHover` to `false` to keep it running. Auto play also pauses while keyboard focus is inside the slider, while the slider is scrolled out of view and while the browser tab is hidden. Moving to another slide restarts the timer.

```html
<Slider stopOnHover={false}> ... </Slider>
```

## Pause Button

When auto play is on, a pause button in the bottom corner stops and restarts it. Content that moves by itself needs a way to stop it, so keep this button unless you give users another one. Hide it with `pauseButton={false}`.

Use `bind:paused` to read the paused state or to pause the slider from your own control.

```html
<script>
  let paused = $state(false)
</script>

<button onclick={() => paused = !paused}>{paused ? "Play" : "Pause"}</button>

<Slider bind:paused pauseButton={false}> ... </Slider>
```

## Timer & Fraction

The `timer` prop shows a progress bar at the top that fills up until the next slide. It is `true` by default and only shows while auto play is on. The `fraction` prop shows a counter like `2 / 5` in the top corner. It is `false` by default. Use either one, both, or neither.

```html
<Slider timer={false} fraction> ... </Slider>
```

## Slide Duration

The `slideDuration` prop sets how long each slide stays, in milliseconds, before auto play moves to the next one. Default is `5000` (5 seconds).

```html
<Slider slideDuration={2000}> ... </Slider>
```

In the example each slide stays for 2 seconds.

## Transition Duration

The `transitionDuration` prop sets how long the move between two slides takes, in milliseconds. Default is `750`. Set it to `0` to change slides instantly.

```html
<Slider transitionDuration={2000}> ... </Slider>
```

In the example each move takes 2 seconds.

## Active Slide

The `activeSlide` prop sets the slide shown first, starting from `1`. Default is `1`. A number above the slide count shows the last slide.

`activeSlide` is bindable: `bind:activeSlide` follows the current slide, and changing the bound value moves the slider. The `onchange` callback runs with the new slide number every time the slide changes.

```html
<script>
  let active = $state(2)
</script>

<button onclick={() => active = 1}>Show 1</button>

<Slider bind:activeSlide={active} onchange={(slide) => console.log(slide)}> ... </Slider>
```

## Loop

By default the slider loops: after the last slide comes the first one, without a jump back. Set `loop` to `false` to stop at the first and last slides.

```html
<Slider loop={false}> ... </Slider>
```

## Effects

The `effect` prop sets how one slide changes to the next: `"slide"` (default), `"fade"`, `"zoom"`, `"flip"` or `"cube"`. Every effect follows a swipe or drag step by step. `perView`, `gap`, `peek` and `centered` only work with `"slide"`.

### Fade

The slides cross-fade.

```html
<Slider effect="fade"> ... </Slider>
```

### Zoom

The new slide grows in while the old one grows past its size and fades out.

```html
<Slider effect="zoom"> ... </Slider>
```

### Flip

The slide flips like a card, side to side. In a vertical slider it flips top to bottom.

```html
<Slider effect="flip"> ... </Slider>
```

### Cube

The slides are the sides of a turning cube. In a vertical slider the cube turns up and down.

```html
<Slider effect="cube" class="bg-gray-900"> ... </Slider>
```

## Ken Burns

The `kenBurns` prop slowly zooms and pans each image while its slide is shown, each slide in a different direction. It works with every effect and only on image slides (a `Slide` with `src`).

```html
<Slider effect="fade" kenBurns transitionDuration={1500}> ... </Slider>
```

## Parallax

### Image Parallax

The `parallax` prop moves the image of each slide slower than the slide, so it lags behind. `parallax` alone uses `0.5`; set a number from `0` to `1` for less or more. At `1` the image stays still and the slide edge wipes across it. It only works with the `"slide"` effect and on image slides.

```html
<Slider parallax> ... </Slider>
<Slider parallax={1}> ... </Slider>
```

### Layer Parallax

Elements inside any slide can move at their own speed while the slide changes. Add these attributes to an element:

- `data-parallax`: how far the element moves, as a part of the slide size. A higher number moves it more; a negative number moves it ahead of the slide.

- `data-parallax-opacity`: the element's opacity when its slide is out of view, so `0` fades it in as the slide arrives.

- `data-parallax-scale`: the element's scale when its slide is out of view, so `0.5` grows it in.

Layers work with every effect.

```html
<Slider>
  <Slide class="h-72 bg-yellow-200">
    <h3 data-parallax="0.6">Layer slide 1</h3>
    <p data-parallax="0.3" data-parallax-opacity="0">Each layer moves at its own speed.</p>
    <button data-parallax-scale="0.5" data-parallax-opacity="0">Read more</button>
  </Slide>
  ...
</Slider>
```

## Vertical Slider

Set `direction="vertical"` to move the slides up and down. A vertical slider needs a height; it is `h-96` by default and you can change it with `class`. The Up and Down arrow keys change slides, the controls sit at the top and bottom, and the dots move to the side.

```html
<Slider direction="vertical" class="h-80"> ... </Slider>
```

## Multiple Slides

### Slides Per View

The `perView` prop shows several slides at once, like a carousel, and `gap` sets the space between them. `gap` takes a number of pixels or any CSS length like `"1rem"`. The slider still moves one slide at a time.

```html
<Slider perView={3} gap={16}> ... </Slider>
```

### Responsive

`perView`, `gap` and `peek` also take a value per screen size, using the Tailwind breakpoints: `base`, `sm`, `md`, `lg`, `xl` and `2xl`. The largest matching screen size is used. Resize the window to see it change.

```html
<Slider perView={{ base: 1, sm: 2, lg: 3 }} gap={{ base: 8, lg: 20 }}> ... </Slider>
```

The screen size is known only in the browser, so a page rendered on the server starts with the `base` value.

## Peek & Centered

### Peek

The `peek` prop shows a part of the previous and next slides at the edges, so users can see there is more. It takes a number of pixels or any CSS length. The peeking slides can't be reached with the keyboard until they move into view.

```html
<Slider peek={{ base: 24, md: 80 }} gap={16}> ... </Slider>
```

### Centered

The `centered` prop places the active slide in the middle, with the other slides on both sides. It is useful with `perView`. Without `loop`, the first and last slides are centered too, with empty space beside them.

```html
<Slider centered perView={3} gap={12}> ... </Slider>
```

To loop, a slider needs more slides than it can show at once: at least `perView + 1`, or `perView + 3` with `peek`. With fewer slides it stops at the ends.

## Thumbnails

The `thumbnails` prop shows a strip of small images under the slider. Clicking one opens its slide, and the active thumbnail stays in the middle of the strip. A thumbnail uses the slide's `src`; set the `thumbnail` prop on a `Slide` to use another image, or for a content slide. A slide without an image shows its number. You can hide the dots with `indicator={false}`.

```html
<Slider thumbnails indicator={false}>
  <Slide src="..." alt="..." />
  <Slide src="..." alt="..." thumbnail="small-image.jpg" />
  <Slide thumbnail="preview.jpg"> <!-- Custom content --> </Slide>
</Slider>
```

## Swipe & Mousewheel

Users can swipe on touch screens and drag with the mouse. The slides follow the finger, and a move of a small part of a slide is enough to change it. A drag never clicks a link or button inside the slide. Turn it off with `swipe={false}`.

The `mousewheel` prop changes slides with the mouse wheel or a trackpad, one slide per gesture. It is `false` by default because it takes over page scrolling while the pointer is on the slider. Without `loop`, the page scrolls normally again at the first and last slides.

```html
<Slider direction="vertical" class="h-80" mousewheel loop={false}> ... </Slider>
```

## Hero & Background Slider

### Hero Slider

The `overlay` snippet holds content that stays on top while the slides change, like a title and a button over a set of images. Links, buttons and fields in the overlay can be clicked, and dragging on the rest of it still swipes the slides. Set a height with `class` for a full-height hero.

```html
<Slider class="h-[80vh]" effect="fade" kenBurns controls={false} ariaLabel="Hero images">
  {#snippet overlay()}
    <div class="size-full flex flex-col items-center justify-center gap-4 bg-black/30 text-white">
      <h1>Build faster with theui</h1>
      <a href="/docs">Get started</a>
    </div>
  {/snippet}
  <Slide src="..." alt="" />
  <Slide src="..." alt="" />
</Slider>
```

### Page Background

To use the slider as the background of the whole page, fix it behind the content and hide the parts users can't reach. The page content covers the slider's own pause button, so hide it and place your own pause button with `bind:paused`. Images that are only decoration can have an empty `alt`.

```html
<script>
  let paused = $state(false)
</script>

<Slider
  class="fixed inset-0 -z-10 h-auto"
  effect="fade"
  kenBurns
  controls={false}
  indicator={false}
  timer={false}
  swipe={false}
  pauseButton={false}
  bind:paused
  ariaLabel="Page background"
>
  <Slide src="..." alt="" />
  <Slide src="..." alt="" />
</Slider>

<button onclick={() => paused = !paused}>{paused ? "Play" : "Pause"} background</button>
```

## Right to Left

In a right-to-left page (`dir="rtl"`), the slider moves the other way: the next slide comes from the left, the controls swap sides, dragging follows the finger, and the Left arrow key goes to the next slide. The direction is read when the slider loads.

## Customization

Use `class` on the `Slider` for the whole slider and on a `Slide` for that slide. Other attributes, like `id`, go on the same element. These props style the other parts:

- `slideClasses`: classes for every slide, like padding, background or rounded corners.

- `controlButtonClasses`: classes for the previous and next buttons, to change their size, color or position.

- `indicatorContainerClasses`: classes for the container of the dots, to change their position or spacing.

- `indicatorClasses`: classes for every dot, to change its shape, size or color.

- `indicatorActiveClasses`: classes added to the dot of the active slide.

- `thumbnailContainerClasses`: classes for the thumbnail strip.

- `thumbnailClasses`: classes for every thumbnail, like its size.

- `thumbnailActiveClasses`: classes added to the thumbnail of the active slide.

- `timerClasses`: classes for the timer bar, like its height or color.

- `fractionClasses`: classes for the fraction counter, like its position or colors.

- `pauseButtonClasses`: classes for the pause button.

- `overlayClasses`: classes for the container of the `overlay` snippet.

Your classes are merged with the default classes, so a class you set replaces the default one it conflicts with.

## Accessibility

The Slider follows the WAI-ARIA carousel pattern, so it works with the keyboard and with screen readers.

#### Keyboard Navigation

When focus is on a control, a dot, a thumbnail or content inside the slider:

- ← and → move to the previous and next slide (↑ and ↓ in a vertical slider).

- Home and End move to the first and last slide.

- Tab moves through the pause button, the controls, the dots and the content of the slides in view.

- Enter or Space press the focused button.

When a key moves away from a slide that had focus, focus moves to the new slide.

#### Screen Reader Support

- The slider is announced as a carousel, named by the `ariaLabel` prop (default `"Slider"`). Give it a name that describes the slides.

- Each slide is announced as a slide with its position, like "2 of 5".

- Slides that are not in view are hidden from screen readers and can't be reached with Tab.

- Slide changes are announced when the user changes the slide, but not during auto play, so they don't interrupt.

- The previous, next, pause, dot and thumbnail buttons have accessible names, and the active dot and thumbnail are marked as current.

#### Motion

- Auto play stops while keyboard focus is inside the slider, and the pause button stops it for good.

- For users who turn on reduced motion in their system, slides change instantly and auto play, the timer, the pause button and the Ken Burns zoom are turned off.

## Configuration

### Slider

#### Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `autoPlay` | boolean | `true` | Moves to the next slide by itself. At the last slide of a slider that doesn't loop, it goes back to the first slide. |
| `paused` | boolean | `false` | Bindable. Auto play is stopped, by the pause button or by your own control. |
| `stopOnHover` | boolean | `true` | Pauses auto play while the mouse is over the slider. |
| `slideDuration` | number | `5000` | Time (in milliseconds) each slide stays before auto play moves to the next one. |
| `transitionDuration` | number | `750` | Time (in milliseconds) the move between two slides takes. 0 changes slides instantly. |
| `activeSlide` | number | `1` | Bindable. The current slide, starting from 1. A number above the slide count shows the last slide. |
| `onchange` | (activeSlide: number) => void | `undefined` | Runs with the new slide number every time the slide changes. |
| `loop` | boolean | `true` | After the last slide comes the first one. Looping needs more slides than the slider shows at once. |
| `swipe` | boolean | `true` | Changes slides by swiping on touch screens and dragging with the mouse. |
| `mousewheel` | boolean | `false` | Changes slides with the mouse wheel or a trackpad, one slide per gesture. |
| `effect` | [SLIDER_EFFECT](https://www.theui.dev/docs/types#slider-effect-type) | `slide` | How one slide changes to the next: "slide", "fade", "zoom", "flip" or "cube". |
| `kenBurns` | boolean | `false` | Slowly zooms and pans the image of each slide while it is shown. Works on image slides only. |
| `parallax` | boolean \| number | `false` | Moves the image of each slide slower than the slide. true is 0.5; a number sets the strength from 0 to 1. Works with the "slide" effect on image slides only. |
| `direction` | [SLIDER_DIRECTION](https://www.theui.dev/docs/types#slider-direction-type) | `horizontal` | Moves the slides side to side or, with "vertical", up and down. A vertical slider is h-96 unless you set a height with class. |
| `perView` | [SLIDER_RESPONSIVE](https://www.theui.dev/docs/types#slider-responsive-type)<number> | `1` | Number of slides shown at once, or a number per screen size. Works with the "slide" effect only. |
| `gap` | [SLIDER_RESPONSIVE](https://www.theui.dev/docs/types#slider-responsive-type)<number \| string> | `0` | Space between slides, in pixels or any CSS length, or a value per screen size. Works with the "slide" effect only. |
| `peek` | [SLIDER_RESPONSIVE](https://www.theui.dev/docs/types#slider-responsive-type)<number \| string> | `0` | Width of the previous and next slides shown at the edges, in pixels or any CSS length, or a value per screen size. Works with the "slide" effect only. |
| `centered` | boolean | `false` | Places the active slide in the middle. Works with the "slide" effect only. |
| `controls` | boolean | `true` | Shows the previous and next buttons. |
| `indicator` | boolean | `true` | Shows a dot for each slide. |
| `thumbnails` | boolean | `false` | Shows a strip of thumbnails under the slider. |
| `timer` | boolean | `true` | Shows a progress bar until the next slide while auto play is on. |
| `fraction` | boolean | `false` | Shows a counter like "2 / 5". |
| `pauseButton` | boolean | `true` | Shows a button that stops and restarts auto play. |
| `ariaLabel` | string | `Slider` | Accessible name of the slider. Describe what the slides show. |
| `slideClasses` | string | `` | Custom classes for every slide. |
| `controlButtonClasses` | string | `` | Custom classes for the previous and next buttons. |
| `indicatorContainerClasses` | string | `` | Custom classes for the container of the dots. |
| `indicatorClasses` | string | `` | Custom classes for every dot. |
| `indicatorActiveClasses` | string | `` | Custom classes added to the dot of the active slide. |
| `thumbnailContainerClasses` | string | `` | Custom classes for the thumbnail strip. |
| `thumbnailClasses` | string | `` | Custom classes for every thumbnail. |
| `thumbnailActiveClasses` | string | `` | Custom classes added to the thumbnail of the active slide. |
| `timerClasses` | string | `` | Custom classes for the timer bar. |
| `fractionClasses` | string | `` | Custom classes for the fraction counter. |
| `pauseButtonClasses` | string | `` | Custom classes for the pause button. |
| `overlayClasses` | string | `` | Custom classes for the container of the overlay snippet. |

#### Dynamic props

| Name | Description |
| --- | --- |
| `class` | Classes for the slider element, merged with the default classes. |

#### Snippets

| Name | Description |
| --- | --- |
| `children` | The Slide components. |
| `prevButton` | Custom content of the previous button, like an icon. |
| `nextButton` | Custom content of the next button, like an icon. |
| `overlay` | Content that stays on top while the slides change, like a hero title and button. |

### Slide

#### Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `src` | string | `undefined` | Image of the slide. Without it, the slide shows its content. |
| `alt` | string | `undefined` | Alternative text of the image. Use an empty string for a decorative image. |
| `href` | string | `undefined` | Makes the whole slide a link, named by the image alt or the slide content. |
| `thumbnail` | string | `undefined` | Image for the thumbnail of this slide. Defaults to src. |

#### Dynamic props

| Name | Description |
| --- | --- |
| `class` | Classes for the slide, merged with the default classes and slideClasses. |

#### Snippets

| Name | Description |
| --- | --- |
| `children` | Custom content of the slide, used when src is not set. |

---

Category: Components
Keywords: slider, carousel, slideshow, hero, parallax, thumbnails, navigation, component, svelte, svelte-5, theui-svelte, component-library, ui, tailwindcss
Full documentation set: https://www.theui.dev/llms-full.txt
