Slider

One number or an ordered range of numbers, chosen by dragging or with the keyboard.

<tp-slider>
Slider
Default density Compact density Restart from the initial state Show the copyable source

Usage

Each value is a native range input inside a visual thumb, so keyboard, form and assistive-technology behavior come from the platform. label shows a visible label and names the control. A live readout is opt-in: give the slider-output part a content resolver, as above, and it shares the header with the label. A label string, slot="label" content or a slider-label part contract enables the Label. A slot="value" or a slider-output part contract enables Output. Output has aria-live="off" and references every Thumb input ID.

Range

Price range
Default density Compact density Restart from the initial state Show the copyable source

A space-separated default-value creates one thumb per value. min-steps-between-values keeps thumbs apart, and thumb-collision-behavior chooses whether a thumb pushes, swaps with or stops at its neighbor. format takes Intl.NumberFormatOptions for the readout and the spoken value; the submitted value stays numeric. Use distinct names such as “Minimum budget” and “Maximum budget” for ranges.

Multiple thumbs and collisions

Any number of values gives one thumb each, and every thumb is its own tab stop. When a moving thumb meets its neighbor, thumb-collision-behavior="push" moves the neighbor along, swap lets it pass and trade places, and none stops it at the min-steps-between-values gap. push moves adjacent enabled Thumbs while preserving separation; reversing the active Thumb retains values already pushed. swap exchanges logical Thumb identities and retains focus/drag ownership.

Push, swap and none
Default density Compact density Restart from the initial state Show the copyable source

Formatting

format and locale shape the readout and the spoken value together. A currency follows the locale’s conventions, and style: 'percent' shows a 0–1 value as a percentage without changing the value itself.

Currency and percent
Default density Compact density Restart from the initial state Show the copyable source

Controlled

Set value to own the values and accept each proposal in onValueChange. Your code can then change the value from outside, such as restoring a preset; step and large-step work in the same fractional units. The mode stays fixed for the lifetime of the element.

Controlled range
Default density Compact density Restart from the initial state Show the copyable source
Restore defaults

For controlled sliders, accept proposals synchronously through value, as shown above. Debouncing that acceptance introduces an actual delay; defer expensive work separately or use tp-value-commit for work needed only after release.

Steps

Step and large step
Default density Compact density Restart from the initial state Show the copyable source

Values snap to step from minimum. Arrow keys move one step; Page Up, Page Down and Shift with an arrow move by large-step. On wide tracks a smaller step makes dragging feel continuous. The numeric value, Output and Thumb remain synchronized. Slider does not animate between discrete values or accept step="any". Invalid or infeasible configuration emits tp-diagnostic and disables adjustment. Shift, Control or Command use largeStep. Page Up/Down use largeStep; Home/End request the bounds under the collision policy.

Vertical

Vertical
Default density Compact density Restart from the initial state Show the copyable source

Without a visible label, name each slider with aria-label. Vertical sliders use Up and Down. A vertical range works the same way, with the label and readout above the track.

Vertical range
Default density Compact density Restart from the initial state Show the copyable source

Readout beside the track

Leave out the visible label, name the slider with aria-label, and the readout moves to the end of the track instead of sitting in a header. This suits dense settings panels. Static slot="value" content remains consumer-owned and is not automatically rewritten. Use a content resolver when the displayed value must follow the Thumb.

Compact readout
Default density Compact density Restart from the initial state Show the copyable source
Corner radius Border width

Bar

Media timeline
Default density Compact density Restart from the initial state Show the copyable source

variant="bar" paints a thumbless track for scrubbing, as in media timelines; the thumb’s input stays for the keyboard and assistive technology. buffered takes [start, end] ranges in value units and shades them on the track, and getAccessibleValueText gives the spoken value its own wording. While the slider is hovered, pointed, dragged or focused, the Track thickens.

Thumbs

Authored thumbs
Default density Compact density Restart from the initial state Show the copyable source

Author tp-slider-thumb children when a thumb needs its own spoken text, a disabled state or a native input reference. Each needs a unique index; values still live on the Slider.

A disabled thumb becomes a fixed barrier the others can’t cross. Thumbs can also be added and removed at runtime: append one with the next index and call setValue() with the new list, or remove one and the Slider trims its values. A controlled list/Thumb count mismatch preserves owner values and disables ambiguous interaction. Once an explicit composition is authored, removing its last Thumb does not silently generate replacement Thumbs.

Fixed start and added thumbs
Default density Compact density Restart from the initial state Show the copyable source
Add return flight Remove

Endpoints and direction

thumb-alignment sets where a thumb sits at the ends of the track: center (the default) lets half the thumb overhang, edge keeps it inside the track, and delayed-edge starts centered and switches to edge once the slider is used. In a right-to-left context the track, fill and Left/Right keys follow the reading direction. Structural hit-target expansion preserves the shared target-size-min even when the visible Thumb is smaller.

Thumb alignment and right to left
Default density Compact density Restart from the initial state Show the copyable source

Forms

Field and form
Default density Compact density Restart from the initial state Show the copyable source
Save limit Reset

The Slider is the one form participant: a range submits each value under the same name, and Reset restores default-value. A wrapping Field supplies the label and description. Named enabled Thumb values serialize under the same name in logical index order. Disabled Thumb values are omitted. Uncontrolled reset restores the declared default; controlled reset leaves the owner authoritative. Restoration updates only uncontrolled state. Moving focus between Thumbs keeps the slider focused; leaving the entire control marks it touched.

States

Disabled and read-only
Default density Compact density Restart from the initial state Show the copyable source

Disabled sliders cannot be focused and submit nothing. Read-only thumbs stay focusable and submit their value, but cannot move.

Events

Change and commit
Default density Compact density Restart from the initial state Show the copyable source
Drag and release to save.

tp-value-change fires on every proposed value while dragging and can be canceled. tp-value-commit fires once on release, or immediately for keyboard changes; use it for saving or other expensive work. Click the track to choose the nearest eligible Thumb. Dragging preserves the grab offset and commits once on release. Pointer cancellation, lost capture, removal and disconnect release the interaction without a delayed commit. No-op or canceled proposals produce no commit notification.

Call preventDefault() on tp-value-change to reject a value. The thumb stays where it was and nothing is committed.

Rejecting values
Default density Compact density Restart from the initial state Show the copyable source
Plans above 800 req/s need an upgrade.

Media extensions

Slider carries optional media capabilities. Media sliders compose tp-slider with these APIs.

Buffer ranges. buffered accepts readonly [start, end][] in value units (property only). Ranges are clamped to the domain, ordered and merged; empty, inverted and non-finite ranges are dropped. Each remaining range renders one slider-buffer part inside the aria-hidden Track, below the Range. The Root publishes --tp-slider-buffer: the percentage position of the end of the range containing the current value (the last value of a range slider), or else of the last range; 0% when nothing is buffered. Draw a single buffer bar from that variable, or style the per-range parts.

Chapter segments. segments accepts readonly { start, end, label? }[] (property only). Segments are clamped, ordered and empty ones dropped; the media layer owns gap filling and overlap trimming. Each chapter publishes --tp-slider-segment-start, --tp-slider-segment-width (domain percentages), --tp-slider-segment-fill and --tp-slider-segment-buffer (percent of that segment below the value or buffer end). The part state contains the segment’s label.

Hover pointer. While a pointer is over the Control without a drag, pointing is true, pointerRatio is the 0–1 domain position and pointerValue is the corresponding unsnapped value. Horizontal RTL mirrors the axis; vertical grows upward; measured edge alignment of the first Thumb is respected. Movement publishes at most once per animation frame. Leaving the Control, starting a drag, disabling the Slider or entering the indeterminate state clears pointing immediately. Each change dispatches the non-cancelable, bubbling, composed tp-slider-pointer-change event with detail: { value, ratio } (null when cleared). Pointer values are presentation input, not value proposals; they never produce tp-value-change.

Silent bounds. Changing minimum, maximum, step, minStepsBetweenValues, buffered or segments never emits tp-value-change, tp-value-commit or their callbacks. An uncontrolled value outside new bounds is reconciled silently; Field still observes the new form value. Controlled values remain owner-normalized as before.

Form opt-out. formAssociatedValue = false (or form-associated-value="false") makes the Slider submit and restore no value, report no validity, ignore form reset and emit no tp-field-value. Value-change and commit events are unchanged. The element class stays form-associated for platform purposes, so an ancestor disabled fieldset still disables it.

const seek = document.querySelector('tp-slider'); seek.formAssociatedValue = false; seek.indeterminateText = 'Time unknown'; seek.maximum = Number.NaN; // before metadata: indeterminate, no diagnostic seek.addEventListener('tp-slider-pointer-change', (event) => { preview.hidden = event.detail.value === null; }); // later seek.maximum = video.duration; seek.buffered = [[0, 42]]; seek.segments = [ { start: 0, end: 60, label: 'Intro' }, { start: 60, end: video.duration, label: 'Main' }, ];

Inline

Inline
Default density Compact density Restart from the initial state Show the copyable source

variant="inline" fits the slider into one row the height of a control, with the label at the start and the value at the end, so several settings stack tightly. The row fills up to the value in the primary color, and a full-height edge marks the value while the row is hovered, dragged or focused. A press anywhere on the row, the label and the value included, moves the value there. Inside a Field, the Field’s label moves into the row. A vertical slider keeps its usual look.

Inline in a field
Default density Compact density Restart from the initial state Show the copyable source

Editable value

Editable value
Default density Compact density Restart from the initial state Show the copyable source

With editable-value, the value of an inline slider can also be typed. A click on the value, or Enter or F2 on the focused slider, turns it into a number field with the value selected. Enter or leaving the field sets the typed value, kept within the range and on the step; Escape puts the value back. A press on the value no longer moves it, while the rest of the row still does. A range keeps its plain value.

Ticks

Ticks
Default density Compact density Restart from the initial state Show the copyable source

ticks draws a mark every so many value units from minimum. Every mark is a value the slider can take, and the midpoint, when it is one, gets a longer center mark. Values still move freely on step, and a drag that passes close to the center stops on it. With snap-to-ticks the ticks become the steps: dragging, the arrow keys and form values all land on a tick. When ticks would crowd a short track, some are left out; the center mark always stays.

API Reference

Every element also accepts motion-policy.

Attributes

AttributePropertyTypeDefaultDescriptiondefault-valuedefaultValueSliderValue | undefined—The initial value of an uncontrolled slider, restored on form reset: a number, or several for a range.minimumminimumnumber0The lowest value.maximummaximumnumber100The highest value.minminnumber—Another name for minimum.maxmaxnumber—Another name for maximum.stepstepnumber1The increment values snap to, counted from minimum.ticksticksnumber | undefined—Draws a tick every this many value units, counted from minimum; the midpoint of the range is drawn as a distinct center tick. Without snapToTicks, a drag near the center lands on it.snap-to-tickssnapToTicksbooleanfalseValues snap to the ticks: the tick interval replaces step for pointer, keys and forms.editable-valueeditableValuebooleanfalseAn inline slider with one value lets its value be typed: a click on the value, or Enter or F2 on the thumb, edits it as a number. A press on the value then no longer moves it; the rest of the bar still does.large-steplargeStepnumber10The increment of Page Up, Page Down and arrow keys with Shift.min-steps-between-valuesminStepsBetweenValuesnumber0The fewest steps kept between neighboring thumbs of a range.variantvariantSliderVariant'default'bar paints a thumbless track; the Thumb stays as the keyboard and accessibility input. inline paints one compact control-height bar with the label and the value inside it, for stacked controls; the value shows without further setup and an enclosing Field's label moves into the bar.thumb-alignmentthumbAlignmentSliderThumbAlignment'center'Whether a thumb centers on its value or stays inside the track at the ends (edge); delayed-edge centers until the first interaction.thumb-collision-behaviorthumbCollisionBehaviorSliderThumbCollisionBehavior—What a thumb dragged into its neighbor does: push it along, swap places with it, or stop.thumb-crossingthumbCrossing'prevent' | 'swap' | undefined—Older name for thumbCollisionBehavior: prevent stops at the neighbor, swap swaps.labellabelstring''Visible label above the track, and the accessible name of the thumbs.localelocalestring''Locale of the formatted values, when it differs from the page's.indeterminate-textindeterminateTextstring''Accessible value text while the domain is indeterminate.form-associated-valueformAssociatedValuebooleantruefalse opts the Slider out of form participation: it submits and restores no value, reports no validity, ignores form reset and emits no tp-field-value.

Properties

PropertyTypeDefaultDescriptionformatIntl.NumberFormatOptions | undefined—Number format of the shown and announced values, such as a currency or a percent.onValueChangeSliderValueChangeCallback | undefined—Called with each proposed value before tp-value-change; a controlled owner accepts it by setting value.onValueCommittedSliderValueCommitCallback | undefined—Called with each committed value before tp-value-commit.getAccessibleLabel((index: number) => string) | undefined—Accessible name of each thumb by index, such as “Minimum price” and “Maximum price”.getAccessibleValueText((formatted: string, value: number, index: number) => string) | undefined—Announced text of a thumb's value, from the formatted value, the number and the index.bufferedreadonly SliderBufferedRange[][]Non-semantic [start, end] ranges in value units, such as buffered media.segmentsreadonly SliderSegment[][]Non-semantic segments of the domain, such as media chapters.valuesread-onlyreadonly number[]—The current values as an array, for a single value too.thumbMetadataread-onlyreadonly SliderThumbMetadata[]—Each thumb's index, input ID, value, position as a percentage and disabled state.activeThumbIndexread-onlynumber—Index of the thumb being dragged or adjusted, or -1.draggingread-onlyboolean—Whether a thumb is being dragged.indeterminateread-onlyboolean—The domain is empty or non-finite: a declared, disabled, non-error state.pointerRatioread-onlynumber | null—Hovered 0–1 domain ratio while pointing over the track without dragging.pointerValueread-onlynumber | null—Unsnapped hovered value while pointing over the track without dragging.pointingread-onlyboolean—The pointer is over the track and no drag is in progress.controlledread-onlyboolean—Whether the application controls value.

Events

EventTypeDescriptiontp-value-changeTpValueChangeEvent<SliderValue | undefined>Cancelable proposal of new values while dragging or adjusting; detail.value, detail.previousValue, detail.reason and detail.metadata.activeThumbIndex.tp-value-commitTpValueCommitEvent<SliderValue | undefined>After a drag is released or a keyboard change is accepted, with the committed value; the moment to save or fetch.tp-field-valueCustomEvent<{ value: SliderValue | undefined; previousValue: SliderValue | undefined; reason: ChangeReason; }>After a value commits; an enclosing Field tracks its dirty state from it.tp-slider-pointer-changeCustomEvent<SliderPointerChangeDetail>{ value, ratio } as the pointer hovers the track without dragging, null when it leaves; for previews such as a media timeline's thumbnail.

Methods

MethodReturnsDescriptionsetValue(value, source?, reason?, reasonOrSource)booleanProposes a value as if set by a thumb, optionally with a reason and a source event, and returns whether it was accepted.

Slots

SlotDescriptiondefaultSlider Thumbs, when the thumbs need their own names, states or customization; without them the Slider renders one per value.labelA rich visible label in place of label.valueCustom content of the value output above the track.

CSS parts

PartDescription::part(slider)The root around the label, the output and the track.::part(slider-buffer)One buffered range drawn on the track, such as loaded media.::part(slider-chapter)One chapter segment of the track, such as a media chapter.::part(slider-label)The visible label above the track, or inside the bar of an inline slider.::part(slider-output)The formatted value beside the label.::part(slider-range)The filled part of the track: up to the value, or between the values of a range.::part(slider-thumb)The handle around each native range input.::part(slider-tick)One tick mark on the track; data-center marks the midpoint and data-filled a tick inside the range.::part(slider-track)The full length of the track.::part(slider-value-editor)The editor of the value while it is typed, in place of the formatted value.

<tp-slider-thumb>

Attributes

AttributePropertyTypeDefaultDescriptiontabindex———Tab order of the native input, moved from the host to the input.indexindexnumber | undefined—Which value of the Slider this thumb controls, from 0; required on every thumb of a range.value-textvalueTextstring | undefined—Announced text of the value, such as “20 to 40 euros”, in place of the formatted number.

Properties

PropertyTypeDefaultDescriptiongetAccessibleLabel((index: number) => string) | undefined—Accessible name of the thumb from its index; takes precedence over the Slider's.getAccessibleValueText((formatted: string, value: number, index: number) => string) | undefined—Announced text of the value from the formatted value, the number and the index; takes precedence over the Slider's.inputIdread-only——ID of the native range input, for labels and outputs that reference it.tabIndexnumber—Tab order of the native input.sliderSliderThumbOwner | null—The Slider that owns the thumb, set when the thumb is connected.variantread-onlySliderVariant—The owning Slider's variant, so the Thumb resolves the same presentation axis.visualElementread-onlyHTMLElement | null—The rendered thumb element around the native input.

CSS parts

PartDescription::part(focusable)The native range input inside the thumb, which takes focus.::part(slider-thumb)The handle around each native range input.

Components, widgets and patterns that use this one.

Show more