An input where the user selects a value from within a given range.
Import
import { Slider } from "@kobalte/core/slider";// orimport { Root, Track, ... } from "@kobalte/core/slider";// or (deprecated)import { Slider } from "@kobalte/core";Features
- Follow the WAI ARIA Slider design pattern.
- Can be controlled or uncontrolled.
- Support for multiple thumbs.
- Support a minimum step between thumbs.
- Support click or touch on track to change value.
- Support right or left direction.
- Support for custom value label.
Anatomy
The slider consists of:
- Slider: The root container for the slider.
- Slider.Track: The component that visually represents the slider track.
- Slider.Fill: The component that visually represents the slider value.
- Slider.Thumb: The thumb that is used to visually indicate a value in the slider.
- Slider.Input: The native html input that is visually hidden in the slider thumb.
- Slider.Label: The label that gives the user information on the slider.
- Slider.ValueLabel: The accessible label text representing the current value in a human-readable format.
- Slider.Description: The description that gives the user more information on the slider.
- Slider.ErrorMessage: The error message that gives the user information about how to fix a validation error on the slider.
<Slider> <Slider.Label /> <Slider.ValueLabel /> <Slider.Track> <Slider.Fill /> <Slider.Thumb> <Slider.Input /> </Slider.Thumb> </Slider.Track> <Slider.Description /> <Slider.ErrorMessage /></Slider>Example
0
import { Slider } from "@kobalte/core/slider";
export function BasicExample() { return ( <Slider class={style.SliderRoot}> <div class={style.SliderLabel}> <Slider.Label>Label</Slider.Label> <Slider.ValueLabel /> </div> <Slider.Track class={style.SliderTrack}> <Slider.Fill class={style.SliderRange} /> <Slider.Thumb class={style.SliderThumb}> <Slider.Input /> </Slider.Thumb> </Slider.Track> </Slider> );}.SliderRoot { position: relative; display: flex; flex-direction: column; align-items: center; user-select: none; touch-action: none; width: 200px;}
.SliderRoot[data-orientation="vertical"] { height: 200px;}
.SliderTrack { background-color: hsl(240 6% 90%); position: relative; border-radius: 9999px; height: 8px; width: 100%;}
.SliderTrack[data-orientation="vertical"] { width: 8px; height: 100%;}
.SliderRange { position: absolute; background-color: hsl(200 98% 39%); border-radius: 9999px; height: 100%;}
.SliderRange[data-orientation="vertical"] { width: 100%; height: unset;}
.SliderThumb { display: block; width: 16px; height: 16px; background-color: hsl(200 98% 39%); border-radius: 9999px; top: -4px;}
.SliderThumb[data-orientation="vertical"] { left: -4px; top: unset;}
.SliderThumb:hover { box-shadow: 0 0 0 5px #2a91fe98;}
.SliderThumb:focus { outline: none; box-shadow: 0 0 0 5px #2a91fe98;}
.SliderLabel { width: 100%; display: flex; justify-content: space-between;}
[data-theme*="dark"] .SliderTrack { background-color: hsl(240 5% 26%);}Usage
Multiple Thumbs
0, 20
import { Slider } from "@kobalte/core/slider";import "./style.css";
function App() { return ( <Slider class="SliderRoot" defaultValue={[0, 20]}> <div class="SliderLabel"> <Slider.Label>Label</Slider.Label> <Slider.ValueLabel /> </div> <Slider.Track class="SliderTrack"> <Slider.Fill class="SliderRange" /> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> <Slider.Thumb class="SliderThumb SliderThumb"> <Slider.Input /> </Slider.Thumb> </Slider.Track> </Slider> );}.SliderRoot { position: relative; display: flex; flex-direction: column; align-items: center; user-select: none; touch-action: none; width: 200px;}
.SliderTrack { background-color: hsl(240 6% 90%); position: relative; border-radius: 9999px; height: 8px; width: 100%;}
.SliderRange { position: absolute; background-color: hsl(200 98% 39%); border-radius: 9999px; height: 100%;}
.SliderThumb { display: block; width: 16px; height: 16px; background-color: hsl(200 98% 39%); border-radius: 9999px; top: -4px;}
.SliderThumb:hover { box-shadow: 0 0 0 5px #2a91fe98;}
.SliderThumb:focus { outline: none; box-shadow: 0 0 0 5px #2a91fe98;}
.SliderLabel { width: 100%; display: flex; justify-content: space-between;}Modify step size
0
0
0
import { Slider } from "@kobalte/core/slider";import "./style.css";
function App() { return ( <> <Slider class="SliderRoot" step={8}> <div class="SliderLabel"> <Slider.Label>Step size 8</Slider.Label> <Slider.ValueLabel /> </div> <Slider.Track class="SliderTrack"> <Slider.Fill class="SliderRange" /> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> </Slider.Track> </Slider> <Slider class="SliderRoot" step={10}> <div class="SliderLabel"> <Slider.Label>Step size 10</Slider.Label> <Slider.ValueLabel /> </div> <Slider.Track class="SliderTrack"> <Slider.Fill class="SliderRange" /> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> </Slider.Track> </Slider> <Slider class="SliderRoot" step={20}> <div class="SliderLabel"> <Slider.Label>Step size 20</Slider.Label> <Slider.ValueLabel /> </div> <Slider.Track class="SliderTrack"> <Slider.Fill class="SliderRange" /> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> </Slider.Track> </Slider> </> );}.SliderRoot { position: relative; display: flex; flex-direction: column; align-items: center; user-select: none; touch-action: none; width: 200px;}
.SliderTrack { background-color: hsl(240 6% 90%); position: relative; border-radius: 9999px; height: 8px; width: 100%;}
.SliderRange { position: absolute; background-color: hsl(200 98% 39%); border-radius: 9999px; height: 100%;}
.SliderThumb { display: block; width: 16px; height: 16px; background-color: hsl(200 98% 39%); border-radius: 9999px; top: -4px;}
.SliderThumb:hover { box-shadow: 0 0 0 5px #2a91fe98;}
.SliderThumb:focus { outline: none; box-shadow: 0 0 0 5px #2a91fe98;}
.SliderLabel { width: 100%; display: flex; justify-content: space-between;}Steps between thumbs
10, 20
import { Slider } from "@kobalte/core/slider";import "./style.css";
function App() { return ( <Slider class="SliderRoot" defaultValue={[10, 20]} minStepsBetweenThumbs={10}> <div class="SliderLabel"> <Slider.Label>Label</Slider.Label> <Slider.ValueLabel /> </div> <Slider.Track class="SliderTrack"> <Slider.Fill class="SliderRange" /> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> <Slider.Thumb class="SliderThumb SliderThumb"> <Slider.Input /> </Slider.Thumb> </Slider.Track> </Slider> );}.SliderRoot { position: relative; display: flex; flex-direction: column; align-items: center; user-select: none; touch-action: none; width: 200px;}
.SliderTrack { background-color: hsl(240 6% 90%); position: relative; border-radius: 9999px; height: 8px; width: 100%;}
.SliderRange { position: absolute; background-color: hsl(200 98% 39%); border-radius: 9999px; height: 100%;}
.SliderThumb { display: block; width: 16px; height: 16px; background-color: hsl(200 98% 39%); border-radius: 9999px; top: -4px;}
.SliderThumb:hover { box-shadow: 0 0 0 5px #2a91fe98;}
.SliderThumb:focus { outline: none; box-shadow: 0 0 0 5px #2a91fe98;}
.SliderLabel { width: 100%; display: flex; justify-content: space-between;}Vertical Slider
0
import { Slider } from "@kobalte/core/slider";import "./style.css";
function App() { return ( <Slider class="SliderRoot" orientation="vertical"> <div class="SliderLabel"> <Slider.Label>Label</Slider.Label> <Slider.ValueLabel /> </div> <Slider.Track class="SliderTrack"> <Slider.Fill class="SliderRange" /> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> </Slider.Track> </Slider> );}.SliderRoot { position: relative; display: flex; flex-direction: column; align-items: center; user-select: none; touch-action: none; height: 200px;}
.SliderTrack { background-color: hsl(240 6% 90%); position: relative; border-radius: 9999px; width: 8px; height: 100%;}
.SliderRange { position: absolute; background-color: hsl(200 98% 39%); border-radius: 9999px; width: 100%;}
.SliderThumb { display: block; width: 16px; height: 16px; background-color: hsl(200 98% 39%); border-radius: 9999px; left: -4px;}
.SliderThumb:hover { box-shadow: 0 0 0 5px #2a91fe98;}
.SliderThumb:focus { outline: none; box-shadow: 0 0 0 5px #2a91fe98;}
.SliderLabel { width: 100%; display: flex; justify-content: space-between;}Custom Value Label
$20 - $500
import { Slider } from "@kobalte/core/slider";import "./style.css";
function App() { return ( <Slider class="SliderRoot" minValue={10} maxValue={2000} defaultValue={[20, 500]} getValueLabel={params => `$${params.values[0]} - $${params.values[1]}`} > <div class="SliderLabel"> <Slider.Label>Money</Slider.Label> <Slider.ValueLabel /> </div> <Slider.Track class="SliderTrack"> <Slider.Fill class="SliderRange" /> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> <Slider.Thumb class="SliderThumb SliderThumb"> <Slider.Input /> </Slider.Thumb> </Slider.Track> </Slider> );}.SliderRoot { position: relative; display: flex; flex-direction: column; align-items: center; user-select: none; touch-action: none; width: 200px;}
.SliderTrack { background-color: hsl(240 6% 90%); position: relative; border-radius: 9999px; height: 8px; width: 100%;}
.SliderRange { position: absolute; background-color: hsl(200 98% 39%); border-radius: 9999px; height: 100%;}
.SliderThumb { display: block; width: 16px; height: 16px; background-color: hsl(200 98% 39%); border-radius: 9999px; top: -4px;}
.SliderThumb:hover { box-shadow: 0 0 0 5px #2a91fe98;}
.SliderThumb:focus { outline: none; box-shadow: 0 0 0 5px #2a91fe98;}
.SliderLabel { width: 100%; display: flex; justify-content: space-between;}Controlled Value
40
import { createSignal } from "solid-js";import { Slider } from "@kobalte/core/slider";import "./style.css";
function App() { const [values, setValues] = createSignal<number[]>([40]);
return ( <Slider class="SliderRoot" value={values()} onChange={setValues}> <div class="SliderLabel"> <Slider.Label>Label</Slider.Label> <Slider.ValueLabel /> </div> <Slider.Track class="SliderTrack"> <Slider.Fill class="SliderRange" /> <Slider.Thumb class="SliderThumb"> <Slider.Input /> </Slider.Thumb> </Slider.Track> </Slider> );}.SliderRoot { position: relative; display: flex; flex-direction: column; align-items: center; user-select: none; touch-action: none; width: 200px;}
.SliderTrack { background-color: hsl(240 6% 90%); position: relative; border-radius: 9999px; height: 8px; width: 100%;}
.SliderRange { position: absolute; background-color: hsl(200 98% 39%); border-radius: 9999px; height: 100%;}
.SliderThumb { display: block; width: 16px; height: 16px; background-color: hsl(200 98% 39%); border-radius: 9999px; top: -4px;}
.SliderThumb:hover { box-shadow: 0 0 0 5px #2a91fe98;}
.SliderThumb:focus { outline: none; box-shadow: 0 0 0 5px #2a91fe98;}
.SliderLabel { width: 100%; display: flex; justify-content: space-between;}API Reference
Slider
Slider is equivalent to the Root import from @kobalte/core/slider (and deprecated Slider.Root).
| Prop | Description |
|---|---|
| value | number[] The controlled values of the slider. Must be used in conjunction with onChange. |
| defaultValue | number[] The value of the slider when initially rendered. Use when you do not need to control the state of the slider. |
| onChange | (value: number[]) => void Event handler called when the value changes. |
| onChangeEnd | (value: number[]) => void Event handler called when the value changes at the end of an interaction. |
| inverted | boolean Whether the slider is visually inverted. Defaults to false. |
| minValue | number The minimum slider value. Defaults to 0 |
| maxValue | number The maximum slider value. Defaults to 100 |
| step | number The stepping interval. Defaults to 1 |
| minStepsBetweenThumbs | number The minimum permitted steps between thumbs. Defaults to 0 |
| getValueLabel | (params: GetValueLabelParams) => string A function to get the accessible label text representing the current value in a human-readable format. If not provided, the value label will be read as a percentage of the max value. |
| orientation | 'horizontal' | 'vertical' The orientation of the slider. |
| name | string The name of the slider, used when submitting an HTML form. |
| validationState | 'valid' | 'invalid' Whether the slider should display its "valid" or "invalid" visual styling. |
| required | boolean Whether the user must check a radio group item before the owning form can be submitted. |
| disabled | boolean Whether the radio group is disabled. |
| readOnly | boolean Whether the radio group items can be selected but not changed by the user. |
| Data attribute | Description |
|---|---|
| data-orientation='horizontal' | Present when the slider has horizontal orientation. |
| data-orientation='vertical' | Present when the slider has vertical orientation. |
| data-valid | Present when the slider is valid according to the validation rules. |
| data-invalid | Present when the slider is invalid according to the validation rules. |
| data-required | Present when the user must slider an item before the owning form can be submitted. |
| data-disabled | Present when the slider is disabled. |
| data-readonly | Present when the slider is read only. |
Slider.ValueLabel, Slider.Fill, Slider.Input, Slider.Thumb and Slider.Track share the same data-attributes.
Rendered elements
| Component | Default rendered element |
|---|---|
Slider | div |
Slider.Track | div |
Slider.Fill | div |
Slider.Thumb | span |
Slider.Input | input |
Slider.ValueLabel | div |
Slider.Description | div |
Slider.ErrorMessage | div |
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| PageUp | Increases the value of the focused thumb by a larger step. |
| PageDown | Decreases the value of the focused thumb by a larger step. |
| ArrowDown | Decreases the value of the focused thumb by the step amount. |
| ArrowUp | Increases the value of the focused thumb by the step amount. |
| ArrowRight | Increments/decrements by the step value depending on orientation. |
| ArrowLeft | Increments/decrements by the step value depending on orientation. |
| Home | Sets the value of the first thumb to the minimum value. |
| End | Sets the value of the last thumb to the maximum value. |
Last updated: 7/16/26, 7:09 AM