Skip to main content
Vuetify0 is now in beta!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

Slider

Headless slider for single-value and range inputs with pointer drag, keyboard navigation, and step snapping.

Usage

The Slider supports single-value and range modes. Add one Slider.Thumb for a single value, or two for a range.

Single and Range Slider

A single-value slider and a range slider with track and thumb components.

Value: 50

Range: 25 – 75

Anatomy

vue
<script setup lang="ts">
  import { Slider } from '@vuetify/v0'
</script>

<template>
  <!-- Single thumb -->
  <Slider.Root>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>

    <Slider.Thumb />
  </Slider.Root>

  <!-- Range (two thumbs) -->
  <Slider.Root>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>

    <Slider.Thumb />
    <Slider.Thumb />
  </Slider.Root>

  <!-- With form submission -->
  <Slider.Root>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>

    <Slider.Thumb />

    <Slider.HiddenInput />
  </Slider.Root>
</template>

Architecture

The Root component composes createSlider for pointer/keyboard interaction and createModel for value storage. Each Thumb registers via a ticket and receives its position as a percentage.

Slider Architecture

Use controls to zoom and pan. Click outside or press Escape to close.

Slider Architecture

The Root creates a slider instance and provides it via context. Track listens for pointer events to update the nearest thumb. Each Thumb registers itself and manages drag/keyboard interaction for its value. Range renders the filled region between thumbs (or from min to a single thumb).

Examples

Audio Equalizer

Multiple vertical sliders composed into a 5-band equalizer with preset management. Each band is an independent Slider.Root with orientation="vertical", bridged to a shared gains array via @update:model-value.

File breakdown:

FileRole
useEqualizer.tsComposable — band definitions, gain state, named presets, apply() and reset()
Equalizer.vueReusable component — renders one vertical Slider per band with dB scale and frequency labels
equalizer.vueDemo — wires preset buttons to the composable

Key patterns:

  • Slider.Thumb v-slot="{ value, isDragging }" drives both the scale animation and the floating dB label that appears only while dragging

  • Each band’s Slider.Root receives a single-element array ([gains[index]]) and writes back via an update function that splices into the shared array

  • The composable owns all state — the component is purely presentational, making it reusable with different band configurations

+120-12
0
60
0
250
0
1k
0
4k
0
16k

HSL Color Picker

Three sliders for Hue, Saturation, and Lightness with reactive gradient tracks and a live color preview. Demonstrates how to hide Slider.Range when the track gradient is the visualization.

File breakdown:

FileRole
ColorSlider.vueReusable gradient slider — accepts a gradient prop for the track background and thumbColor for dynamic thumb styling
ColorPicker.vueComposes three ColorSliders with reactive gradients that update when hue changes, plus a color swatch and hex output
color-picker.vueDemo — adds clickable color presets that set all three models at once

Key patterns:

  • Slider.Range is omitted entirely — the gradient track replaces it as the visual indicator

  • Slider.Thumb uses data-[state=dragging]:scale-125 for drag feedback without needing slot props — the component sets left automatically via its internal attrs.style

  • Saturation and lightness gradients are toRef derivations that recompute when hue changes, making the tracks shift color in real time

  • defineModel with named models (v-model:hue, v-model:saturation, v-model:lightness) gives the parent fine-grained control over each channel

HSL220°, 80%, 55%HEX#306ee8
Hue220
Saturation80
Lightness55
Presets

Recipes

Form Integration

Set name on Root to auto-render hidden inputs for form submission — one per thumb:

vue
<template>
  <Slider.Root name="price" :min="0" :max="1000">
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>

    <Slider.Thumb />
  </Slider.Root>
</template>

Drag Events

Root emits start and end for pointer drag lifecycle:

vue
<template>
  <Slider.Root
    v-model="value"
    @start="onStart"
    @end="onEnd"
  >
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>

    <Slider.Thumb />
  </Slider.Root>
</template>

Data Attributes

Style interactive states without slot props:

vue
<template>
  <Slider.Thumb class="data-[state=dragging]:scale-125 transition-transform" />
</template>
AttributeValuesComponents
data-statedragging, idleThumb
data-disabledtrueRoot, Track, Range, Thumb
data-readonlytrueRoot, Track, Range, Thumb
data-orientationhorizontal, verticalRoot, Track, Range

Accessibility

Each Slider.Thumb manages its own ARIA attributes automatically.

ARIA Attributes

AttributeValueNotes
rolesliderApplied to each Thumb
aria-valuenowCurrent valueUpdates on drag/keyboard
aria-valueminMin valueFrom Root’s min prop
aria-valuemaxMax valueFrom Root’s max prop
aria-valuetextCustom textOptional, via Thumb prop
aria-orientationhorizontal / verticalReflects Root orientation
aria-disabledtrueWhen slider is disabled
aria-readonlytrueWhen slider is readonly
tabindex0 / removedRemoved when disabled

Keyboard Navigation

KeyAction
ArrowRight / ArrowUpIncrement by one step
ArrowLeft / ArrowDownDecrement by one step
Shift+ArrowIncrement/decrement by 10 steps
PageUpIncrement by 10 steps
PageDownDecrement by 10 steps
HomeSet to minimum
EndSet to maximum
Was this page helpful?

Ctrl+/