---
title: "Slider"
description: "An input where the user selects a value from within a given range."
canonical_url: "https://vinicunca.dev/akar/components/slider"
---
# Slider

> An input where the user selects a value from within a given range.

```vue [index.vue]
<script setup lang="ts">
import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'akar'
import { ref } from 'vue'
import './styles.css'

const sliderValue = ref([50])
</script>

<template>
  <div class="akar-demo akar-demo-Slider">
    <SliderRoot
        v-model="sliderValue"
        class="SliderRoot"
        :max="100"
        :step="1"
      >
        <SliderTrack class="SliderTrack">
          <SliderRange class="SliderRange" />
        </SliderTrack>
        <SliderThumb
          class="SliderThumb"
          aria-label="Volume"
        />
      </SliderRoot>
  </div>
</template>
```

```css [styles.css]
@import '../_colors/black-alpha.css';
@import '../_colors/grass.css';

@scope (.akar-demo-Slider) {
.SliderRoot {
  position: relative;
  display: flex;
  align-items: center;
  user-select: none;
  touch-action: none;
  width: 200px;
  height: 20px;
}

.SliderTrack {
  background-color: var(--black-a10);
  position: relative;
  flex-grow: 1;
  border-radius: 9999px;
  height: 3px;
}

.SliderRange {
  position: absolute;
  background-color: white;
  border-radius: 9999px;
  height: 100%;
}

.SliderThumb {
  display: block;
  width: 20px;
  height: 20px;
  background-color: white;
  box-shadow: 0 2px 10px var(--black-a7);
  border-radius: 10px;
}
.SliderThumb:hover {
  background-color: var(--grass-3);
}
.SliderThumb:focus {
  outline: none;
  box-shadow: 0 0 0 5px var(--black-a8);
}
}
```

## Features

- Can be controlled or uncontrolled.
- Supports multiple thumbs.
- Supports a minimum value between thumbs.
- Supports touch or click on track to update value.
- Supports Right to Left direction.
- Full keyboard navigation.

## Installation

Install the component from your command line.

```bash [pnpm]
pnpm add akar
```

```bash [yarn]
yarn add akar
```

```bash [npm]
npm install akar
```

```bash [bun]
bun add akar
```

## Anatomy

Import all parts and piece them together.

```vue
<script setup>
import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'akar';
</script>

<template>
  <SliderRoot>
    <SliderTrack>
      <SliderRange />
    </SliderTrack>
    <SliderThumb />
  </SliderRoot>
</template>
```

## API Reference

### Root

Contains all the parts of a slider. It will render an `input` for each thumb when used within a `form` to ensure events propagate correctly.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `defaultValue` | `[0]` | `number[]` | The value of the slider when initially rendered. Use when you do not need to control the state of the slider. |
| `dir` |  | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.<br><br>If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. |
| `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the slider. |
| `inverted` | `false` | `boolean` | Whether the slider is visually inverted. |
| `max` | `100` | `number` | The maximum value for the range. |
| `min` | `0` | `number` | The minimum value for the range. |
| `minStepsBetweenThumbs` | `0` | `number` | The minimum permitted steps between multiple thumbs. |
| `modelValue` |  | `number[] \| null` | The controlled value of the slider. Can be bind as `v-model`. |
| `name` |  | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. |
| `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation of the slider. |
| `required` |  | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. |
| `step` | `1` | `number` | The stepping interval. |
| `thumbAlignment` | `"contain"` | `"contain" \| "overflow"` | The alignment of the slider thumb.<br>- `contain`: thumbs will be contained within the bounds of the track.<br>- `overflow`: thumbs will not be bound by the track. No extra offset will be added. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:modelValue` | `payload: number[]` | Event handler called when the slider value changes |
| `valueCommit` | `payload: number[]` | Event handler called when the value changes at the end of an interaction.<br><br>Useful when you only need to capture a final value e.g. to update a backend service. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `modelValue` | `number[] \| null` | Current slider values |

[SliderRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Slider/SliderRoot.vue)

| Data attribute | Value |
| --- | --- |
| `[data-disabled]` | Present when disabled |
| `[data-orientation]` | "vertical" \\| "horizontal" |

### Track

The track that contains the `SliderRange`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[SliderTrack.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Slider/SliderTrack.vue)

| Data attribute | Value |
| --- | --- |
| `[data-disabled]` | Present when disabled |
| `[data-orientation]` | "vertical" \\| "horizontal" |

### Range

The range part. Must live inside `SliderTrack`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[SliderRange.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Slider/SliderRange.vue)

| Data attribute | Value |
| --- | --- |
| `[data-disabled]` | Present when disabled |
| `[data-orientation]` | "vertical" \\| "horizontal" |

### Thumb

A draggable thumb. You can render multiple thumbs.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[SliderThumb.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Slider/SliderThumb.vue)

| Data attribute | Value |
| --- | --- |
| `[data-disabled]` | Present when disabled |
| `[data-orientation]` | "vertical" \\| "horizontal" |

## Examples

### Vertical orientation

Use the `orientation` prop to create a vertical slider.

```vue
// index.vue
<script setup>
import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'akar'
</script>

<template>
  <SliderRoot
    class="SliderRoot"
    :default-value="[50]"
    orientation="vertical"
  >
    <SliderTrack class="SliderTrack">
      <SliderRange class="SliderRange" />
    </SliderTrack>
    <SliderThumb class="SliderThumb" />
  </SliderRoot>
</template>
```

```css
/* styles.css */
.SliderRoot {
  position: relative;
  display: flex;
  align-items: center;
}
.SliderRoot[data-orientation="vertical"] {
  flex-direction: column;
  width: 20px;
  height: 100px;
}

.SliderTrack {
  position: relative;
  flex-grow: 1;
  background-color: grey;
}
.SliderTrack[data-orientation="vertical"] {
  width: 3px;
}

.SliderRange {
  position: absolute;
  background-color: black;
}
.SliderRange[data-orientation="vertical"] {
  width: 100%;
}

.SliderThumb {
  display: block;
  width: 20px;
  height: 20px;
  background-color: black;
}
```

### Create a range

Add multiple thumbs and values to create a range slider.

```vue
// index.vue
<script setup>
import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'akar'
</script>

<template>
  <SliderRoot :default-value="[25, 75]">
    <SliderTrack>
      <SliderRange />
    </SliderTrack>
    <SliderThumb />
    <SliderThumb />
  </SliderRoot>
</template>
```

### Define step size

Use the `step` prop to increase the stepping interval.

```vue
// index.vue
<script setup>
import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'akar'
</script>

<template>
  <SliderRoot
    :default-value="[50]"
    :step="10"
  >
    <SliderTrack>
      <SliderRange />
    </SliderTrack>
    <SliderThumb />
  </SliderRoot>
</template>
```

### Prevent thumb overlap

Use `minStepsBetweenThumbs` to avoid thumbs with equal values.

```vue
// index.vue
<script setup>
import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'akar'
</script>

<template>
  <SliderRoot
    :default-value="[25, 75]"
    :step="10"
    :min-steps-between-thumbs="1"
  >
    <SliderTrack>
      <SliderRange />
    </SliderTrack>
    <SliderThumb />
    <SliderThumb />
  </SliderRoot>
</template>
```

## Accessibility

Adheres to the [Slider WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/slidertwothumb).

### Keyboard Interactions

| Key | Description |
| --- | --- |
| <kbd>ArrowRight</kbd> | Increases the value by the `step` amount. |
| <kbd>ArrowLeft</kbd> | Decreases the value by the `step` amount. |
| <kbd>ArrowUp</kbd> | Increases the value by the `step` amount. |
| <kbd>ArrowDown</kbd> | Decreases the value by the `step` amount. |
| <kbd>PageUp</kbd> | Increases the value by a larger `step`. |
| <kbd>PageDown</kbd> | Decreases the value by a larger `step`. |
| <kbd>Shift + ArrowUp</kbd> | Increases the value by a larger `step`. |
| <kbd>Shift + ArrowDown</kbd> | Decreases the value by a larger `step`. |
| <kbd>Home</kbd> | Sets the value to its minimum. |
| <kbd>End</kbd> | Sets the value to its maximum. |

#### Inverted sliders

When the slider is `inverted`, some controls are inverted as well, depending on the `orientation`.

- When the slider is `horizontal` (the default), `→`, `←`, `Home`, and `End` are inverted.
- When the slider is `vertical`, `↑`, `↓`, `PageUp`, `PageDown`, `Shift + ArrowUp`, and `Shift + ArrowDown` are inverted.

## Custom APIs

Create your own API by abstracting the primitive parts into your own component.

### Abstract all parts

This example abstracts all of the `Slider` parts so it can be used as a self closing element.

#### Usage

```vue
<script setup lang="ts">
import { Slider } from './your-slider';
</script>

<template>
  <Slider :default-value="[25]" />
</template>
```

#### Implementation

```ts
// your-slider.ts
export { default as Slider } from 'Slider.vue';
```

```vue
<!-- Slider.vue -->
<script setup lang="ts">
import type { SliderRootEmits, SliderRootProps } from 'akar';
import { SliderRange, SliderRoot, SliderThumb, SliderTrack, useForwardPropsEmits } from 'akar';

const props = defineProps<SliderRootProps>();
const emits = defineEmits<SliderRootEmits>();

const forward = useForwardPropsEmits(props, emits);
</script>

<template>
  <SliderRoot
    v-slot="{ modelValue }"
    v-bind="forward"
  >
    <SliderTrack>
      <SliderRange />
    </SliderTrack>

    <SliderThumb
      v-for="(_, i) in modelValue"
      :key="i"
    />
  </SliderRoot>
</template>
```

## Caveats

### Mouse events are not fired

Because of [a limitation](https://github.com/unovue/reka-ui/blob/v2/packages/core/src/Slider/SliderImpl.vue#L48-L49) we faced during implementation, the following example won't work as expected and the `@mousedown` and `@mousedown` event handlers won't be fired:

```vue
<SliderRoot
  @mousedown="() => { console.log('onMouseDown')  }"
  @mouseup="() => { console.log('onMouseUp')  }"
>
  …
</SliderRoot>
```

We recommend using pointer events instead (eg. `@pointerdown`, `@pointerup`). Regardless of the above limitation, these events are better suited for cross-platform/device handling as they are fired for all pointer input types (mouse, touch, pen, etc.).

---

- [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/slidertwothumb)
- [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Slider)
- [npm](https://www.npmjs.com/package/akar)


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
