Range
Accessible range slider that allows easy selection of a value by sliding a handle.
View SourceInstallation
Follow instructions for individual framework usage below
Styles
Variants
Props
Tokens
Scripts
The Range script updates track CSS variables and linked output values as the slider changes.
Examples
Default
html
<x-range class="x-range">
<input type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" data-x-range-part="start">
</x-range>
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>liquid
<div data-controller="x-range" class="x-range">
<input type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" data-x-range-target="start" data-action="input->x-range#setValue">
</div>
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>vue
<script setup lang="ts">
import { ref } from 'vue'
import { Range } from '@/components/range'
const startElement = ref<HTMLInputElement>()
</script>
<template>
<Range v-slot="{ setValue }" :refs="{ startElement }">
<input ref="startElement" type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" @input="setValue">
</Range>
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
</template>tsx
import { useRef } from "react"
import { Range } from "@/components/range"
export function Example() {
const startElement = useRef<HTMLInputElement>(null)
return (
<>
<Range refs={{ startElement }}>
{({ setValue }) => (
<input ref={startElement} type="range" defaultValue="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" onInput={setValue} />
)}
</Range>
<output className="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
</>
)
}Multi
html
<x-range class="x-range accent-warning">
<input type="range" value="0" step="100" max="10000" min="0" id="range-from" aria-labelledby="from" data-x-range-part="start">
<input type="range" value="10000" step="100" max="10000" min="0" id="range-to" aria-labelledby="to" data-x-range-part="end" data-track="end">
</x-range>
<div class="flex-between items-center">
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price from" id="from">0</output>
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price to" id="to">10 000</output>
</div>liquid
<div data-controller="x-range" class="x-range accent-warning">
<input type="range" value="0" step="100" max="10000" min="0" id="range-from" aria-labelledby="from" data-x-range-target="start" data-action="input->x-range#setValue">
<input type="range" value="10000" step="100" max="10000" min="0" id="range-to" aria-labelledby="to" data-x-range-target="end" data-action="input->x-range#setValue" data-x-range-track-param="end">
</div>
<div class="flex-between items-center">
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price from" id="from">0</output>
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price to" id="to">10 000</output>
</div>vue
<script setup lang="ts">
import { ref } from 'vue'
import { Range } from '@/components/range'
const startElement = ref<HTMLInputElement>()
const endElement = ref<HTMLInputElement>()
</script>
<template>
<Range v-slot="{ setValue }" :refs="{ startElement, endElement }" class="accent-warning">
<input ref="startElement" type="range" value="0" step="100" max="10000" min="0" id="range-from" aria-labelledby="from" @input="setValue">
<input ref="endElement" type="range" value="10000" step="100" max="10000" min="0" id="range-to" aria-labelledby="to" @input="setValue">
</Range>
<div class="flex-between items-center">
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price from" id="from">0</output>
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price to" id="to">10 000</output>
</div>
</template>tsx
import { useRef } from 'react'
import { Range } from '@/components/range'
export function Example() {
const startElement = useRef<HTMLInputElement>(null)
const endElement = useRef<HTMLInputElement>(null)
return (
<>
<Range className="accent-warning" refs={{ startElement, endElement }}>
{({ setValue }) => (
<>
<input ref={startElement} type="range" defaultValue="0" step="100" max="10000" min="0" id="range-from" aria-labelledby="from" onInput={setValue} />
<input ref={endElement} type="range" defaultValue="10000" step="100" max="10000" min="0" id="range-to" aria-labelledby="to" onInput={setValue} />
</>
)}
</Range>
<div className="flex-between items-center">
<output className="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price from" id="from">0</output>
<output className="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price to" id="to">10 000</output>
</div>
</>
)
}Vertical
html
<x-range class="x-range vertical h-48">
<input type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" data-x-range-part="start">
</x-range>
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>liquid
<div data-controller="x-range" class="x-range vertical h-48">
<input type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" data-x-range-target="start" data-action="input->x-range#setValue">
</div>
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>vue
<script setup lang="ts">
import { ref } from 'vue'
import { Range } from '@/components/range'
const startElement = ref<HTMLInputElement>()
</script>
<template>
<Range v-slot="{ setValue }" :refs="{ startElement }" class="vertical h-48">
<input ref="startElement" type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" @input="setValue">
</Range>
<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
</template>tsx
import { useRef } from 'react'
import { Range } from '@/components/range'
export function Example() {
const startElement = useRef<HTMLInputElement>(null)
return (
<>
<Range className="vertical h-48" refs={{ startElement }}>
{({ setValue }) => (
<input ref={startElement} type="range" defaultValue="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" onInput={setValue} />
)}
</Range>
<output className="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
</>
)
}JavaScript API
setTrackProperty
- Type:
(options: TrackOptions, track: 'start' | 'end') => void - Kind:
sync
TrackOptions
element
- Type:
HTMLElement | Element - Default:
undefined
value
- Type:
string - Default:
undefined
min
- Type:
number - Default:
undefined
max
- Type:
number - Default:
undefined
setValue
- Type:
(element: HTMLInputElement, options: SetValueOptions) => void - Kind:
sync
DefaultOptions
selector
- Type:
string - Default:
.x-range
track
- Type:
string - Default:
'start' | 'end'
setOutputValue
- Type:
(element: HTMLInputElement, options: SetOutputOptions) => void - Kind:
sync
SetOutputOptions
lang
- Type:
string - Default:
document.documentElement.lang
formatOptions
- Type:
Intl.NumberFormatOptions - Default:
{ style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0 }