Skip to content

Slider ​

A slider built on an enhanced native <input type="range">.

Basic Usage ​

Basic usage

Range & Step ​

min / max / step

Disabled ​

Disabled

Readonly ​

readonly (focusable, not dimmed, not draggable)

readonly is independent of disabled: a readonly slider stays focusable and its value still participates in form collection, but dragging and keyboard edits are intercepted; visually it is not dimmed (unlike the disabled state) — suitable for configuration summaries.

Marks (object) ​

Marks object: value → label map

Marks (array) ​

Marks array: values only, labels fall back to the numeric text

While dragging, tick marks and labels reached by the current value are highlighted with the theme color. marks supports both a JSON object {"value":"label"} and a JSON array [value, value] (array elements may also be {"value": 26, "label": "26°C"}).

Marks-only values (step="mark") ​

step=mark: values snap to marks (XS/S/M/XL discrete choice)

The special value step="mark" restricts selectable values to the marks value set: dragging and the keyboard (arrows jump between marks, Shift/PageUp jump 3 marks at a time, Home/End go to the first/last mark) all snap to the nearest mark; continuous values outside marks are not selectable. Requires marks; without marks it falls back to a plain step of 1.

Tick stops (show-stops) ​

show-stops: tick dots by step (no label data needed)

show-stops renders tick dots along the track by step (no labels), highlighted where passed; independent of marks — when both exist, marks take precedence (no stacking). Dots are not rendered when they exceed 100 (DOM explosion guard).

With Input ​

show-input numeric input linkage

The numeric input on the right stays in sync with the slider in both directions: dragging updates the input live; typing takes effect after a 300ms debounce and is automatically clamped to the min/max range, Enter/blur commits immediately.

Pointer Scrubbing & Double-Click Reset ​

Press-drag the readout (scrub) + double-click track to reset

The readout supports pointer scrubbing: press and drag the numeric input horizontally — 4px per step (step size = step) — ideal for dense parameter tuning where precise clicking is awkward. Modifier keys share the knob convention: Shift for fine adjustment (×0.2), Alt for ultra-fine (×0.04); no acceleration tier. Dragging back to the press point restores the original value (mistaken drags are losslessly undone); movement under one step counts as a plain click (focus/typing still works). Scrubbing dispatches oas-input while dragging and commits oas-change on release. Under step="mark" scrub values snap to the nearest mark in real time (second slider — the value always stays on the mark set).

Double-click the track to reset to reset-value (falls back to min when unset); reset goes through the full commit chain (oas-input + oas-change) and only responds in single-value mode. Scrubbing is not enabled on coarse pointers (tap-to-focus typing takes priority); set scrub="false" to disable entirely.

Pro Attributes (precision / value-width / accent-color / show-track) ​

precision rounding + value-width readout width

accent-color (scrub accent) + show-track="false" (track hidden)

  • precision: decimal places for the value — scrub steps and the bubble/aria-valuetext are rounded accordingly; when unset, float tails are auto-collapsed to the effective decimals of step/modifier (implementation error like 0.1 + 0.2 never reaches the value channel), an explicit value acts as a stricter constraint (e.g. 0 clamps modifier fine-steps back to integers), with lower priority than the format/formatTooltip channels;
  • value-width: readout box width; plain numbers get px, unit values pass through (defaults to 72px);
  • accent-color: the readout accent color while scrubbing; preset semantic names map to theme tokens (dark-theme aware), other values pass through;
  • show-track: track visibility switch — show-track="false" hides the track bar and selection fill (the thumb remains, still draggable and keyboard operable), suited to embedding the slider in custom containers keeping only the thumb.

Range Mode ​

range dual-thumb interval + dual inputs

range enables dual-thumb interval selection. value is a JSON array [lo, hi] or a comma-separated string "lo,hi"; combined with show-input you can edit the min/max inputs separately. Out-of-range inputs follow the "push along" rule: typing a min beyond max pushes max along, and vice versa. After interaction the value attribute is written back as a JSON array string, ready for JSON.parse in form collection.

Custom Thumb ​

custom-thumb icon thumb + value bubble

Value bubble only (no custom content)

Customize the thumb content (icon/text) via template[slot="custom-thumb"] (or a plain [slot="custom-thumb"] element); the content is cloned into every visible thumb. show-tooltip shows a value bubble above the thumb, and both coexist. In range mode the template is cloned into both the min and max thumbs.

Value bubble formatting & always-on ​

format template string: ${value} placeholder (bubble and screen reader share the source)

formatTooltip function channel + tooltip-always (currency format)

tooltip-position bubble direction (bottom)

Bubble content supports dual-channel formatting; the output feeds both the bubble and aria-valuetext (screen reader matches the visual):

  • format attribute: a template string where ${value} is replaced with the current value (e.g. "${value}%", "¥${value}"); shown as-is when no placeholder is present;
  • el.formatTooltip function property: assign in JS as el.formatTooltip = (value) => string, suited to Intl currency/unit closures; takes precedence over format, clear with null.

Visibility: shown while dragging or when keyboard-focused by default; tooltip-always keeps it visible; tooltip-position switches the direction (top/bottom/left/right; top by default horizontally, right by default vertically).

Fill start point (start-point) ​

start-point: fill extends from the midpoint (thermometer)

start-point sets the fill origin for single-value mode (default min): the fill extends right when the value is above the start, left when below — ideal for ± intervals (temperature/gain). The start is clamped to [min, max]; ignored in range mode (the interval fill is determined by both thumbs).

Sizes ​

size sm / md / lg

size switches three track/thumb sizes (also accepts small/medium/large, supports config-provider injection); invalid values fall back to md.

Thumb Shape (thumb) ​

thumb two shapes: round thumb (default) / pointer

thumb switches the handle shape: round is the default thick circular thumb; pointer is a thin pointer (a slim bar sitting along the axis — suited to color tracks/waveforms where precise reading matters and the track should stay visible). pointer always uses the custom visual layer (native thumb hidden): a thin vertical bar horizontally, a thin horizontal bar vertically; invalid values fall back to round.

Stereo Level Meter (levels) ​

levels {left,right}: dual level bars below the round thumb (0–1 normalized)

levels renders a dual stereo level meter below the round thumb ({ left, right }, normalized 0–1, clamped) — suited to audio/mixer faders. The meter is decorative (aria-hidden, non-interactive); it renders only for thumb="round" (the default) and is ignored for thumb="pointer". You can also assign functionally: el.levels = { left, right } (clear with null).

Colors ​

color / track-color

color controls the fill/thumb/passed-tick color and track-color the track base color: preset semantic names (primary/success/warning/danger, following dark theme automatically) map to theme tokens; any other value (e.g. #ff5500, var(--x)) is passed through as a CSS color.

Color Track (track) ​

track color rails: hue / saturation / luminance / gradient

track turns the rail into a color-space gradient rail — suited to picking color/brightness/gain, where the track itself expresses the value:

  • hue: full hue spectrum (red → yellow → green → cyan → blue → magenta → red);
  • saturation: neutral gray (--oas-color-border-strong) → thumb color (saturation);
  • luminance: black → white (brightness);
  • gradient: track base (--oas-slider-track) → thumb color (--oas-slider-color), a two-stop CSS gradient.

The gradient direction is axis- and direction-aware: left-to-right horizontally, bottom-to-top vertically, mirrored under reverse/RTL. While a color track is active the single-color fill is hidden (the spectrum speaks for itself); the rail can still be recolored via track-color and the thumb via color. Non-preset values fall back to a plain solid track.

Vertical ​

vertical sliders (volume/brightness panel)

vertical switches to a vertical slider (minimum at the bottom; reverse mirrors to the top): mark labels move to the right of the track, the value bubble faces right by default, and show-input inputs move below the track. Height defaults to 200px, adjustable via the --oas-slider-height CSS variable. The handle shape is controlled by thumb (pointer thin pointer / round circular thumb, see Thumb Shape).

Reverse ​

reverse direction (min on the right)

reverse flips the value direction so the minimum sits on the right; the fill, ticks and custom thumb positions mirror accordingly. In vertical mode reverse puts the minimum at the top.

Keyboard ​

Keyboard large step (large-step)

With the thumb focused: arrows / Home / End keep the native browser stepping; Shift + arrows and PageUp / PageDown step by the large amount = large-step (default 10 × step), unified across browsers (smoothing over Firefox's native PageUp differences). Each key press commits immediately (emits oas-input + oas-change).

Slider with label ​

oas-form-item composition (label + slider layout)

The slider has no built-in visible label (avoiding duplication with the form label system): use oas-form-item's label for a visible label (clicking the label focuses the slider), or lay out a heading + slider yourself.

Accessible Name (label) ​

label accessible name

Inspect aria-label

label becomes the accessible name of the inner slider (aligned with the input label contract): single sliders get aria-label = label; range mode composes localized semantic suffixes ("Volume Minimum" / "Volume Maximum"); when unset, the built-in fallback text is used. Screen readers and voice control rely on this name.

Events ​

Live value & change events

Range mode events (detail.value is an array)

oas-input fires while dragging, oas-change fires on release: detail.value is a number in single mode and a [lo, hi] array in range mode:

Multiple Thumbs (N-element array) ​

Three thumbs: N-element value + per-thumb accessible names

Multiple thumbs + numeric input linkage

value accepts an N-element array (JSON array or comma-separated string) and renders N thumbs — range is the N=2 special case (keeping the legacy range-min/range-max contract); a two-plus element array also renders multiple thumbs without range. Each thumb drags and responds to the keyboard independently, values stay ascending (dragging past a neighbour clamps), and the oas-input / oas-change detail.value is an array. Per-thumb accessible names come from the labels JSON array (labels='["Low","Mid","High"]') or label-1/label-2… attributes; the fallback is label + index (or the built-in text plus index).

API ​

oas-slider ​

Attributes ​

AttributeDescriptionTypeDefault
accent-colorAccent color while scrubbing the readout: preset semantic names (primary / success / warning / danger, dark-theme aware) map to theme tokens, other values pass through; falls back to the theme primary——
colorFill/thumb/passed-tick color: preset semantic names (primary / success / warning / danger, following dark theme) map to theme tokens; any other value is passed through as a CSS color——
disabledDisabledboolean—
formatValue bubble template string: ${value} is replaced with the current value (e.g. "${value}%"); shown as-is without a placeholder; the output feeds both the bubble and aria-valuetext; lower priority than the formatTooltip functionstring—
labelAccessible name for the inner slider (range mode appends localized min/max suffixes)string—
label-1Accessible name for thumb 1 (multi-thumb mode; takes precedence over labels/label)——
label-2Accessible name for thumb 2 (multi-thumb mode; takes precedence over labels/label)——
label-3Accessible name for thumb 3 (multi-thumb mode; takes precedence over labels/label)——
label-4Accessible name for thumb 4 (multi-thumb mode; takes precedence over labels/label)——
label-5Accessible name for thumb 5 (multi-thumb mode; takes precedence over labels/label)——
label-6Accessible name for thumb 6 (multi-thumb mode; takes precedence over labels/label)——
label-7Accessible name for thumb 7 (multi-thumb mode; takes precedence over labels/label)——
label-8Accessible name for thumb 8 (multi-thumb mode; takes precedence over labels/label)——
labelsJSON string array of per-thumb accessible names (e.g. ["Low","Mid","High"]; the label-N attribute family takes precedence)string—
large-stepKeyboard large step amount (Shift+arrows / PageUp / PageDown); defaults to 10 × step; each key press emits oas-input + oas-changestring—
levelsStereo level meter: { left, right } normalized values (0–1, clamped) rendered as dual bars below the round thumb (decorative aria-hidden, non-interactive); renders only for thumb="round" (the default) and is ignored for pointer; invalid/missing hides it{ left?: number; right?: number } | string | null—
marksTicks: JSON object {"0":"0°C"} (value→label) or JSON array [0,26,60] (also {"value":26,"label":"26°C"}); tick marks and labels are shown below the track, highlighted where the value passes; positions mirror under reversestring | Record<string, string | number> | number[]—
maxRangestring100
minRangestring0
precisionDecimal places for the value (scrub steps and the bubble/aria-valuetext are rounded accordingly; when unset, float tails are auto-collapsed to the effective decimals of step/modifier, an explicit value acts as a stricter constraint); lower priority than format/formatTooltip channelsstring—
rangeRange mode: dual-thumb interval selection, value as JSON array [lo, hi] or comma-separated string "lo,hi"; thumbs constrain each other (lo ≤ hi), event detail.value is an arrayboolean—
readonlyReadonly (independent of disabled): stays focusable and the value still participates in form collection; dragging and keyboard edits are intercepted; not visually dimmedboolean—
reset-valueDouble-click-track reset target: falls back to min when unset; clamped to [min, max] and snapped to the nearest mark under step="mark"; single-value mode only (ignored for range/multi); reset dispatches oas-input + oas-changestring—
reverseReversed direction: minimum on the right horizontally (track dir="rtl"), at the top vertically; fill/ticks/custom thumb positions mirror accordinglyboolean—
scrubReadout pointer scrubbing (on by default): press and drag the readout horizontally — 4px per step (step size = step); Shift for fine (×0.2), Alt for ultra-fine (×0.04, aligned with knob; no acceleration tier); drag back to the press point to restore the original value; movement under one step counts as a plain click (typing preserved); scrub="false" disables; not enabled on coarse pointersstringtrue
show-inputShow a numeric input on the right, synced bidirectionally with the slider: dragging updates the input live; typing commits after a 300ms debounce and is clamped to min/max, Enter/blur commits immediately; range mode shows min/max inputs (min beyond max pushes max along)boolean—
show-stopsRender tick dots along the track by step (no labels), highlighted where passed; marks take precedence when both exist; dots are not rendered beyond 100boolean—
show-tooltipShow a value bubble above the thumb (temporarily shown while dragging; coexists with custom-thumb)boolean—
show-trackTrack visibility switch (shown by default); show-track="false" hides the track bar and selection fill (the thumb remains draggable and keyboard operable)stringtrue
sizeThree sizes: sm / md / lg (also accepts small / medium / large, supports config-provider injection); track height and thumb diameter scale together; invalid values fall back to mdstringmedium
start-pointFill origin for single-value mode (default min): the fill extends right above the start and left below it; clamped to [min, max]; ignored in range modestring—
stepStep; the special value "mark" restricts selectable values to the marks set (dragging/keyboard/controlled values snap to the nearest mark; requires marks, falls back to 1)string1
thumbThumb shape: round thick circular thumb (default) / pointer thin pointer (a slim bar along the axis; always uses the custom visual layer with the native thumb hidden — thin vertical bar horizontally, thin horizontal bar vertically); invalid values fall back to roundstringround
tooltip-alwaysKeep the value bubble always visible (by default shown while dragging or keyboard-focused)boolean—
tooltip-positionValue bubble direction: top / bottom / left / right; top by default horizontally, right by default vertically; invalid values fall back to the defaultstring—
trackColor rail preset: hue hue spectrum / saturation neutral gray→thumb color / luminance black→white / gradient track base→thumb color (a two-stop CSS gradient); direction is axis- and reverse/RTL-aware; the single-color fill is hidden while active (the spectrum speaks for itself); non-preset values fall back to a solid trackstring—
track-colorTrack base color: preset semantic names map to theme tokens; any other value is passed through as a CSS color——
valueCurrent value (controlled): numeric string for single mode; JSON array [lo, hi] or comma-separated string "lo,hi" in range mode, written back as a JSON array string after interaction (form collection can JSON.parse directly)number | number[]—
value-widthWidth of the show-input readout box: plain numbers get px, unit values pass through (written to --oas-slider-value-width); defaults to 72pxstring—
verticalVertical mode: the track runs vertically (minimum at the bottom, mirrored to the top by reverse); mark labels move to the right of the track, the value bubble faces right by default, show-input inputs move below the track; height defaults to 200px, adjustable via the --oas-slider-height CSS variableboolean—

Property (JS property; see each row for attribute reflection) ​

PropertyDescriptionTypeDefault
levelsStereo level values { left, right } (normalized 0–1; object assignment reflects to a JSON attribute, clear with null){ left?: number; right?: number } | string | null—
valueCurrent value: a number for a single thumb, or an array of numbers for multiple thumbsnumber | number[]—

Events ​

EventDescription
oas-changeCommitted on release, detail: { value } (single number; [lo, hi] array in range mode)
oas-inputWhile dragging / after debounced typing commit, detail: { value } (single number; [lo, hi] array in range mode)

Slots ​

NameDescription
template[slot="custom-thumb"]Custom thumb content (icon/text): template[slot="custom-thumb"] (static template, cloned into every visible thumb — both thumbs in range mode) or a plain [slot="custom-thumb"] element

CSS Variables ​

CSS VariableDescriptionDefault
--oas-glass-refractionLiquid-glass edge refraction filter (active under data-glass, default none); for local opt-out override with an empty value (--oas-glass-refraction: ;)—not none (mixing none with button-state brightness() invalidates the whole filter declaration)none
--oas-slider-accent—var(--oas-color-primary)
--oas-slider-color—var(--oas-color-primary)
--oas-slider-height—200px
--oas-slider-thumb-size—14px
--oas-slider-track—var(--oas-color-border)
--oas-slider-track-imageColor-rail gradient image (written by the component for a track preset; the track pseudo-element's background-image, defaults to none for a solid rail color)none
--oas-slider-track-size—4px
--oas-slider-value-width—72px

marks also accepts a JS property channel (assign objects/arrays directly, reflected as a JSON attribute); el.formatTooltip = (value) => string | number is the value formatter function property (the output feeds both the value bubble and aria-valuetext, takes precedence over the format attribute, clear with null) — attributes cannot express function semantics, so the function channel is JS-property-only.

Released under the MIT OR Apache-2.0 License.