Slider Documentation has not yet been reviewed by a human.
Slider selects a number or an interval within a numeric range. Use it for
settings such as volume, playback speed, or price limits when dragging helps
people choose a value. Use a separate numeric input when precise text entry is
also useful.
Give every slider a visible label or an accessible name. A string label supplies
the name; pair a rich label with aria-label or aria-labelledby.
Playground
Managing the value
Pass defaultValue for an uncontrolled slider, or use value with
onValueChange when the application owns the number. A controlled slider changes
only when you update value. Turn off Accept changes in this example to see
requests without applying them. Reset to 35% changes the application value
without requesting another change.
Applied: 35%. Requested: 35%.
import { useState } from 'preact/hooks'import { Button, Checkbox, Slider } from '@antadesign/anta'
function SliderOwnershipDemo() { const [value, setValue] = useState(35) const [accept, setAccept] = useState(true) const [requested, setRequested] = useState(35)
return ( <> <Checkbox label="Accept changes" checked={accept} onStateChange={(_, { next }) => setAccept(next === true)} /> <Slider label="Volume" value={value} valueSuffix="%" onValueChange={(_, { value: next }) => { setRequested(next) if (accept) setValue(next) }} /> <Button onClick={() => setValue(35)}>Reset to 35%</Button> <p>Applied: {value}%. Requested: {requested}%.</p> </> )}0 is a controlled numeric value. Omitting value or passing undefined selects
uncontrolled use. Releasing control retains the last applied number until
interaction or reset changes it. A numeric slider has no empty value.
onValueChange reports requested values while dragging. onValueCommit reports
the final request when the gesture ends, including cancellation or capture loss,
and after each keyboard step. Its value can differ from the applied value when
the application rejects a controlled request. onInput runs before
onValueChange; onChange runs before onValueCommit. Cancel a keyboard or
pointer default in onKeyDown or onPointerDown; the value notifications are
noncancelable. See the prop reference for callback snapshots and reset behavior.
Forms
Pass name to include the applied number in form submission. A range submits two
entries under the same name; read them with FormData.getAll(name). Disabled
sliders submit nothing.
Form reset restores an uncontrolled slider’s defaultValue. Without one, it
restores min, or [min, max] for a range. A changed uncontrolled reset emits
both value callbacks. Controlled reset retains the application’s value, and
restoration does not overwrite a controlled value. Restoration of an uncontrolled
value is silent.
<form> <Slider label="Brightness" name="brightness" defaultValue={60} valueSuffix="%" /> <Button type="reset">Reset brightness</Button></form>Relative dragging
With the default trackClick="drag-only", pressing the rail starts dragging
from the current value. Moving right increases the value, and moving left
decreases it. The thumb does not move to the point where the rail was pressed.
Set trackClick="jump" to move the thumb to the pressed position before
dragging, as a native range input does.
Releasing the pointer or losing pointer capture ends the drag. Moving back over the slider without pressing leaves its value unchanged.
Slider is horizontal. In inherited RTL, its minimum is at the right edge and horizontal pointer and arrow movement follow that direction. Up and Down still increase and decrease the value. Vertical orientation and readonly mode are not part of its API. The control reserves touch gestures for dragging.
Arrow keys change by step. Home selects the minimum; End selects the nearest allowed
step to the maximum. PageUp and PageDown move by one tenth of the range.
<Slider label="Relative drag" defaultValue={35} /><Slider label="Jump on press" defaultValue={35} trackClick="jump" />Range values
Pass two numbers to value or defaultValue to show two thumbs. Drag either
thumb across the other to move past it. The thumb you grabbed keeps moving, and
the value stays ordered from low to high. For example, dragging the thumb at 20
past 70 to 85 changes [20, 70] to [70, 85]. Both thumbs can share a value.
Each thumb has its own keyboard focus. Their tab order stays fixed when they
cross.
onValueChange receives a number for a single-value slider and an ordered
[number, number] tuple for a range slider. onValueCommit uses the same shape.
For an uncontrolled range without defaultValue, form reset selects [min, max].
onValueChange: —
import { useState } from 'preact/hooks'import { Slider } from '@antadesign/anta'
function SliderRangeDemo() { const [value, setValue] = useState<[number, number]>([20, 70]) const [lastChange, setLastChange] = useState<[number, number] | null>(null)
return ( <> <Slider label="Selected interval" value={value} onValueChange={(_, { value: next }) => { setValue(next) setLastChange(next) }} /> <p className="range-demo-output"><code>onValueChange</code>: <code>{lastChange ? JSON.stringify(lastChange) : '—'}</code></p> </> )}Inverted fill
inverted to fill the other part of the rail. For one thumb, the fill runs
from the value to the maximum. For two thumbs, the fill covers the rail outside
the selected interval. The minimum and maximum stay at their usual rail ends;
thumb movement and keyboard controls stay the same. <Slider label="Inverted single value" defaultValue={40} inverted /><Slider label="Inverted range" defaultValue={[20, 70]} inverted />Value placement
valueDisplay="end" is the default. Use inline for Label: value, thumb to keep a value above the thumb, or none to omit it. valuePrefix and valueSuffix add text to every live value display. <Slider label="End" defaultValue={48} valueSuffix="%" /><Slider label="Inline" defaultValue={48} valueDisplay="inline" valueSuffix="%" /><Slider label="Thumb" defaultValue={48} valueDisplay="thumb" valueSuffix="%" />Size, tones, and radius
size follows the input height scale: 24px, 28px, and 32px. trackSize sets the thickness of both rail segments without changing the control height; numbers use pixels and strings accept CSS lengths. thumbSize controls the thumb diameter, and thumbFill fills it with its resolved border color. tone colors the filled rail. thumbTone separately colors the thumb stroke. The unfilled rail stays neutral. round shapes both the rail and thumb. Pass true for fully round corners or a number or CSS length for a shared custom radius.
In the Antithesis theme, an omitted thumbTone follows the filled rail’s color.
Other themes keep the thumb neutral. Pass thumbTone="neutral" to keep a neutral
thumb in every theme. The native range uses the same rule for thumb-tone.
<Slider size="small" tone="info" label="Small" defaultValue={32} /><Slider tone="brand" thumbTone="success" trackSize={4} thumbSize={20} thumbFill label="Medium, filled thumb" defaultValue={52} /><Slider size="large" tone="success" round={4} label="Large, 4px corners" defaultValue={72} />Markers
markers places compact, muted labels below the rail. Values at or below min align left; values at or above max align right. Markers do not add dots or ticks to the rail. <Slider label="Playback speed" min={0.5} max={2} step={0.25} defaultValue={1} valueSuffix="×" markers={[ { value: 0.5, label: '0.5×' }, { value: 1, label: 'Normal' }, { value: 2, label: '2×' }, ]}/> Component props
| Prop | Type | Default | Description |
|---|---|---|---|
| label? | ReactNode | — | Visible field label, shown above the rail. A string supplies the slider's
accessible name; give a rich label an explicit aria-label. |
| value? | numberSliderRangeValue | — | Controlled numeric value. A pair selects a range, ordered low to high.
Omit or pass undefined for uncontrolled use; 0 stays controlled.
Runtime null is treated as omission; it is not a controlled empty value.
Takes precedence over defaultValue, including on form reset. Values are
clamped to the bounds and rounded to a step measured from min.
Releasing control retains the last applied value. There is no empty numeric state. |
| defaultValue? | numberSliderRangeValue | min | Initial uncontrolled value and form-reset baseline. Changes while pristine
update the value; after interaction they affect the next reset. Without a
default, scalar reset uses min and range reset uses [min, max]. |
| min? | number | 0 | Lowest permitted value and step origin. Nonfinite values use 0. |
| max? | number | 100 | Highest permitted value. A lower bound than min collapses the range to
min. Nonfinite values use 100. |
| step? | number | 1 | Smallest keyboard and drag increment. Nonpositive and nonfinite values use 1. Page keys move by at least one step, or one tenth of the range. |
| name? | string | — | Form field name. A range submits two values under this name. |
| disabled? | boolean | — | Disables pointer and keyboard interaction. |
| tone? | neutralbrandcriticalinfosuccesswarningstring | 'neutral' | Color of the filled rail. Pass a named tone or a literal CSS color for a one-off custom tone. The unfilled rail stays neutral. |
| thumbTone? | neutralbrandinfosuccesswarningcriticalstring | 'neutral' (the Antithesis theme follows `tone`) | Color of the thumb stroke. Pass a named tone or a literal CSS color for a
one-off custom tone. An explicit neutral keeps the thumb neutral in every theme. |
| size? | smallmediumlarge | 'medium' | Size variant. small=24px, medium=28px, large=32px tall. |
| trackSize? | numberstring | 2 | Thickness of both rail segments. Numbers use pixels; strings are CSS lengths. Keep it no larger than the thumb diameter. |
| thumbSize? | numberstring | 16 | Diameter of the thumb. Numbers use pixels; strings are CSS lengths. Keep
it at least as large as trackSize. |
| thumbFill? | boolean | false | Fill the thumb with its resolved border color. This follows thumbTone
and interactive states. |
| round? | booleannumberstring | — | Fully round the rail and thumb. Pass a number (px) or CSS length string for a shared custom radius. |
| valueDisplay? | endinlinethumbnone | 'end' | Where the live value appears. end puts it at the right edge of the label
row. inline renders Label: value. thumb keeps it above the thumb. |
| valuePrefix? | string | — | Text inserted before the live numeric value, such as $. |
| valueSuffix? | string | — | Text inserted after the live numeric value, such as % or °C. |
| markers? | SliderMarker[] | — | Compact text labels positioned below the rail. They do not add dots or ticks to the rail. |
| trackClick? | drag-onlyjump | 'drag-only' | Controls what happens when the rail is pressed. drag-only starts dragging
from the current value. jump first moves to the pressed position. |
| inverted? | boolean | — | Fill the rail outside the selected value or range. |
| onValueChange? | (event, attrs) => void | — | Reports each distinct requested value during a drag and each keyboard step.
onInput runs first. The snapshot contains the requested value and effective
constraints; the element's value remains the applied value. Controlled
sliders accept by updating value and reject by leaving it unchanged.
Events are notifications; preventDefault() does not veto a value request. |
| onValueCommit? | (event, attrs) => void | — | Reports the final requested value after a drag, cancellation, or capture loss,
and after each keyboard step. onChange runs first. A drag ending at its
starting value is silent. Controlled requests can commit without being accepted.
Uncontrolled form reset emits both callbacks when it changes the value;
state restoration and application updates are silent. |
Inherited props (children, className, id, slot, style, tabIndex, title)
| Prop | Type | Default | Description |
|---|---|---|---|
| children? | ReactNode | — | Child elements. When provided, replaces the component's default label/content. |
| className? | string | — | CSS class on the component's root element (merged with the component's own
classes). Use it directly for layout and positioning — grid/flex placement,
margins, alignment — rather than wrapping the component in a <div>/<span>. |
| id? | string | — | HTML id attribute. |
| slot? | string | — | Assigns the element to a named <slot> of a parent web component (e.g.
slot="header" inside a <Dialog>, slot="footer" inside a <Dialog>). |
| style? | CSSProperties | — | Inline styles on the component's root element. Set layout/positioning here
(or via className) directly on the component instead of adding a wrapper. |
| tabIndex? | number | — | Tab order. Set to -1 to skip the element when tabbing. |
| title? | string | — | HTML title attribute — native browser tooltip on hover. |
Plus every standard DOM event handler (onClick,
onFocus, onKeyDown, …) and any
data-* or aria-* attribute — forwarded as-is to
the underlying <a-*> element.
Web Component
Use <a-slider> with value for a controlled value or default-value for an
uncontrolled initial value. Reading the value property returns the applied
number or sorted pair. input and change events carry request snapshots in
event.detail; accept a controlled request by assigning event.detail.value to
the value property. Application updates are silent. See
Install and configure for imports and hydration setup.
Setting the value property reflects the controlled value attribute. Removing
that attribute, or assigning null or undefined to the property, releases
control and retains the last applied number. Assigning defaultValue reflects
default-value. Uncontrolled interaction, reset, and restoration never rewrite
these attributes. The applied value stays in internal state and form submission.
Add tabindex="0" to a scalar slider, and supply its accessible name. The element
provides the default slider or group role through ElementInternals.
For a range, separate the two numbers with a space in value or default-value.
Use role="group" and give the range an accessible name. Each thumb receives
its own slider role and keyboard focus. The element’s value property and
change events expose a two-number array. If you set name, form submission
includes both values in low-to-high order. Read them with FormData.getAll(name).
<a-slider role="slider" tabindex="0" aria-label="Volume" name="volume" default-value="50" track-size="4px" thumb-fill thumb-size="20px" value-suffix="%"> <span slot="label">Volume</span></a-slider><a-slider role="group" aria-label="Selected interval" name="interval" default-value="20 70" inverted> <span slot="label">Selected interval</span></a-slider>Native HTML range input
Add data-anta to a native range input for Anta’s rail, fill, thumb, and focus
treatment while retaining the browser’s form, keyboard, and pointer behavior.
Use size="small" or "large" for the 24px and 32px control sizes.
track-size accepts a CSS length and changes both rail segments. tone,
thumb-tone, thumb-fill, thumb-size, and round use the same attributes
as Slider. In raw HTML, round needs a CSS length such as "4px"; JSX
round={4} remains a numeric pixel value.
<input data-anta type="range" min="0" max="100" value="48" aria-label="Native range"><input data-anta type="range" min="0" max="100" value="32" size="small" tone="info" aria-label="Small info native range"><input data-anta type="range" min="0" max="100" value="52" tone="brand" thumb-tone="success" track-size="4px" thumb-fill thumb-size="20px" aria-label="Brand native range with a large filled success thumb"><input data-anta type="range" min="0" max="100" value="72" size="large" tone="success" round="4px" aria-label="Large rounded success native range">Styling
Styling
Slider renders an <a-slider> with a circular thumb. tone and thumbTone accept named or custom CSS colors; custom values use the public --slider-tone-source and --slider-thumb-tone-source knobs. Use round to shape the rail and thumb together. Target its shadow parts to change their presentation without taking on the interaction code: ::part(thumb) customizes the thumb’s surface and stroke. Existing parts remain available: header, label, value, control, track,
fill, thumb, thumb-value, markers, and extras. thumb-1 and thumb-2
identify physical thumbs and retain their identity when crossing. Additional parts
include rail-area, inline-value, end-value, value-separator, value-affix,
fill-start, fill-end, thumb-value-1, and thumb-value-2.
Defaults load from external CSS, including styles for these shadow parts. Place
consumer overrides in components, utilities, or unlayered CSS; earlier base
rules lose to Anta defaults. Load Slider CSS in the same root as the host when
rendering inside a consumer shadow root. Existing part names may have additional
tokens, so use [part~="thumb"] for shadow queries.
Public host states describe applied presentation: range, dragging,
pointer-focus, thumb-1-active, and thumb-2-active. The active-thumb states
identify the most recently focused or pressed physical thumb. Region states
has-header, has-markers, has-extras, has-fill, has-fill-end,
has-thumb-value, and has-thumb-value-end indicate visible regions, including
coincident range bubbles.
Custom colors, radius, sizing, marker positions, and application style props can
serialize inline style attributes during SSR. Under style-src-attr 'none', use
external consumer CSS for those values; see CSP guidance.
Default external styling does not remove that separate inline-style constraint.
/* The class is only for the demo. Use your own selector. */.warm-slider::part(fill) { background: #e5484d; }.warm-slider::part(thumb) { background: #fff7ed; border-color: #e5484d; border-radius: 4px;}Editable value beside the label
Compose Input and Slider as separate controls. The grid puts the label and
small input on one row and the slider underneath. Pass valueDisplay="none" so the
slider does not repeat its value. Keep the input’s text as a draft; when the
field loses focus or you press Enter, commit a number within the slider’s range.
Dragging or using the slider’s keyboard controls updates both values.
import { useState } from 'preact/hooks'import { Input, Slider } from '@antadesign/anta'
function SliderEditableValueDemo() { const [value, setValue] = useState(55) const [draft, setDraft] = useState('55')
const commit = () => { const number = Number(draft) const next = draft.trim() && Number.isFinite(number) ? Math.max(0, Math.min(100, Math.round(number))) : value setValue(next) setDraft(String(next)) }
return ( <div className="editable-slider"> <span className="editable-slider-label">Volume</span> <Input aria-label="Volume value" size="small" inputMode="numeric" trailing="%" value={draft} onInput={(event) => setDraft(event.currentTarget.value)} onBlur={commit} onKeyDown={(event) => { if (event.key === 'Enter') commit() }} /> <Slider aria-label="Volume" value={value} valueDisplay="none" valueSuffix="%" onValueChange={(_, { value: next }) => { setValue(next) setDraft(String(next)) }} /> </div> )}.editable-slider { display: grid; grid-template-columns: minmax(0, 1fr) 72px; align-items: center; gap: 0 12px; width: min(100%, 360px); margin-inline: auto;}.editable-slider-label { color: var(--text-3); font-size: 15px; font-weight: 500;}.editable-slider > a-slider { grid-column: 1 / -1; }