Skip to main content
You are viewing Pre-Alpha documentation.
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

A headless slider component for building single-value and range inputs with pointer drag, keyboard navigation, and step snapping. Uses createSlider internally, which delegates value storage to createModel.


IntermediateMar 12, 2026

Usage

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

Value: 50

Range: 25 – 75

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

  const single = ref([50])
  const range = ref([25, 75])
</script>

<template>
  <div class="flex flex-col gap-6">
    <!-- Single -->
    <div class="flex flex-col gap-2">
      <Slider.Root v-model="single" class="relative flex items-center w-full h-5">
        <Slider.Track class="relative h-1 w-full rounded-full bg-surface-variant">
          <Slider.Range class="absolute h-full rounded-full bg-primary" />
        </Slider.Track>

        <Slider.Thumb class="absolute size-5 rounded-full bg-primary -translate-x-1/2 focus:outline-2 focus:outline-primary" />
      </Slider.Root>

      <p class="text-sm text-on-surface-variant">Value: {{ single[0] }}</p>
    </div>

    <!-- Range -->
    <div class="flex flex-col gap-2">
      <Slider.Root v-model="range" class="relative flex items-center w-full h-5" :min-steps-between-thumbs="5">
        <Slider.Track class="relative h-1 w-full rounded-full bg-surface-variant">
          <Slider.Range class="absolute h-full rounded-full bg-primary" />
        </Slider.Track>

        <Slider.Thumb class="absolute size-5 rounded-full bg-primary -translate-x-1/2 focus:outline-2 focus:outline-primary" />
        <Slider.Thumb class="absolute size-5 rounded-full bg-primary -translate-x-1/2 focus:outline-2 focus:outline-primary" />
      </Slider.Root>

      <p class="text-sm text-on-surface-variant">Range: {{ range[0] }} – {{ range[1] }}</p>
    </div>
  </div>
</template>

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

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

API Reference

The following API details are for all variations of the Slider component.

Slider.Root

Props

name

string

Form field name — triggers hidden inputs

namespace

string

Namespace for context provision

Default: "v0:slider:root"

id

string

Unique identifier (auto-generated if not provided)

Default: useId()

min

number

Minimum value (default: 0)

Default: 0

max

number

Maximum value (default: 100)

Default: 100

step

number

Step increment (default: 1)

Default: 1

disabled

MaybeRefOrGetter<boolean>

Disables the slider

Default: false

readonly

MaybeRefOrGetter<boolean>

Readonly — focusable but not editable

orientation

"horizontal" | "vertical"

Slider orientation

Default: "horizontal"

inverted

boolean

Flip the percent axis

Default: false

minStepsBetweenThumbs

number

Minimum steps between adjacent thumbs (default: 0)

Default: 0

crossover

boolean

Allow thumbs to pass through each other (default: false)

Default: false

form

string

Associate with form by ID

modelValue

number | number[]

Default: []

Events

update:model-value

[value: number | number[]]

start

[value: number | number[]]

end

[value: number | number[]]

Slots

default

SliderRootSlotProps

Slider.HiddenInput

Props

namespace

string

Namespace for context injection from parent Slider.Root

Default: "v0:slider:root"

index

number

Thumb index to read value from

Default: 0

Slider.Range

Props

namespace

string

Namespace for connecting to parent Slider.Root

Default: "v0:slider:root"

Slots

default

SliderRangeSlotProps

Slider.Thumb

Props

namespace

string

Namespace for connecting to parent Slider.Root

Default: "v0:slider:root"

ariaLabel

string

Accessible label for this thumb

ariaLabelledby

string

ID of element labelling this thumb

ariaValuetext

string

Custom aria-valuetext (for formatted display)

Slots

default

SliderThumbSlotProps

Slider.Track

Props

namespace

string

Namespace for connecting to parent Slider.Root

Default: "v0:slider:root"

Slots

default

SliderTrackSlotProps

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
Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/