Skip to content

Slider

Stable

Selects a value, or a range of values, by dragging along a track — best when the approximate position matters more than the exact number.

Anatomy

  1. 1TrackThe full range of values, in a neutral tint.
  2. 2RangeThe selected part of the range, filled with the brand color — from the start, or between two thumbs.
  3. 3ThumbThe handle. It's the focusable part, with a 32px hit area; add a second thumb to select a range.

Installation

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/slider.json

Usage

import { Slider } from "@/components/ui/slider"
<Slider defaultValue={50} aria-label="Volume" />

Pass a number for a single thumb and an array for a range — one thumb per value. The filled part of the track and the thumb's border use the brand color.

Examples

With a label and value

Show the current value next to the label whenever the number matters. Label the slider with aria-labelledby pointing at a visible label; the name is forwarded to the thumb, the element screen readers actually focus.

80%

Range

An array value renders two thumbs. minStepsBetweenValues keeps them from overlapping, and getAriaLabel gives each thumb its own name — Minimum price and Maximum price — so they aren't announced as two identical sliders.

$240$760

Steps

step snaps the value to increments. For a handful of discrete values, draw tick labels under the track and describe the value in words with getAriaValueText3 replicas is clearer than 3.

3 × 1 vCPU

Vertical

orientation="vertical" suits controls that map to height — levels, equalizers, zoom. Give the slider a height through its container.

60 Hz
230 Hz
910 Hz
3.6 kHz
14 kHz

Disabled

A disabled slider keeps showing its value at half opacity and ignores input. Say why nearby when it isn't obvious.

Guidelines

When to use

  • When relative position matters more than precision: volume, opacity, zoom, a price range.
  • When people benefit from seeing the value in the context of its full range.

When not to use

  • When an exact number matters — use an Input with type="number", or pair the slider with one.
  • For very large ranges where one pixel covers many values — use an input.
  • For a few named options — use a Radio Group or Toggle Group.

Show the value

A slider without a visible value asks people to guess. Show the value next to the label, format it ($240, 80%) with the format prop or your own formatter, and update it live while dragging.

Opacity80%
Do.The current value is visible and formatted.
Opacity
Don’t.Without a value, people can only estimate what they've chosen.

Commit, don't flood

onValueChange fires continuously while dragging — use it to update the display. Use onValueCommitted to save or fetch once the drag ends, so a single adjustment doesn't send fifty requests.

Accessibility

Each thumb contains a native <input type="range">, so the slider works with screen readers, voice control and browser form features out of the box.

KeyBehavior
Tab
Moves focus to the next thumb. Each thumb of a range is its own tab stop.
Increases the value by one step.
Decreases the value by one step.
PageUpShift
Increases the value by the large step (10 by default).
PageDownShift
Decreases the value by the large step.
HomeEnd
Sets the minimum or maximum value.
  • Name it. Use aria-labelledby pointing at a visible label, or aria-label. prfct forwards the name to the thumbs; for ranges, name each thumb with getAriaLabel.
  • Describe the value. format shapes both the visible and the announced value; getAriaValueText overrides what's announced when words say it better than numbers.
  • Boundaries. The thumb has a 2px brand border, keeping it at least 3:1 against any surface (WCAG 1.4.11). The track isn't needed to identify the control, so it stays quiet.
  • Target size. Thumbs are 16px with a transparent hit area of 32×32px, and grow slightly while hovered or dragged.

API reference

Slider

Renders a <div role="group"> with a track and one thumb per value. Accepts every prop of Base UI's Slider.Root.

PropTypeDefault
value

The value, or values for a range. Use with onValueChange when controlled.

number | number[]No default
defaultValue

The initial value when uncontrolled. An array creates a range.

number | number[]No default
onValueChange

Fires continuously while the value changes.

(value, details) => voidNo default
onValueCommitted

Fires once when a drag or key press ends — use it to save.

(value, details) => voidNo default
min

The lowest value.

number0
max

The highest value.

number100
step

The increment values snap to.

number1
largeStep

The increment for Page Up/Down and Shift+Arrow keys.

number10
minStepsBetweenValues

Minimum distance between the thumbs of a range, in steps.

number0
orientation

Direction of the track.

"horizontal" | "vertical""horizontal"
format

Formats the value for assistive technology and Slider.Value.

Intl.NumberFormatOptionsNo default
aria-label

Accessible name, forwarded to the thumbs.

stringNo default
aria-labelledby

Id of a visible label, forwarded to the thumbs.

stringNo default
getAriaLabel

Names each thumb of a range individually.

(index: number) => stringNo default
getAriaValueText

Custom announced text for the value.

(formatted, value, index) => stringNo default
thumbCollisionBehavior

What happens when range thumbs meet.

"push" | "swap" | "none""push"
name

Submits the value with a form.

stringNo default
disabled

Ignores input and fades the slider.

booleanfalse