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-valuetextare rounded accordingly; when unset, float tails are auto-collapsed to the effective decimals ofstep/modifier (implementation error like0.1 + 0.2never reaches the value channel), an explicit value acts as a stricter constraint (e.g.0clamps modifier fine-steps back to integers), with lower priority than theformat/formatTooltipchannels;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):
formatattribute: a template string where${value}is replaced with the current value (e.g."${value}%","¥${value}"); shown as-is when no placeholder is present;el.formatTooltipfunction property: assign in JS asel.formatTooltip = (value) => string, suited to Intl currency/unit closures; takes precedence overformat, clear withnull.
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
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
| Attribute | Description | Type | Default |
|---|---|---|---|
accent-color | Accent 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 | — | — |
color | Fill/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 | — | — |
disabled | Disabled | boolean | — |
format | Value 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 function | string | — |
label | Accessible name for the inner slider (range mode appends localized min/max suffixes) | string | — |
label-1 | Accessible name for thumb 1 (multi-thumb mode; takes precedence over labels/label) | — | — |
label-2 | Accessible name for thumb 2 (multi-thumb mode; takes precedence over labels/label) | — | — |
label-3 | Accessible name for thumb 3 (multi-thumb mode; takes precedence over labels/label) | — | — |
label-4 | Accessible name for thumb 4 (multi-thumb mode; takes precedence over labels/label) | — | — |
label-5 | Accessible name for thumb 5 (multi-thumb mode; takes precedence over labels/label) | — | — |
label-6 | Accessible name for thumb 6 (multi-thumb mode; takes precedence over labels/label) | — | — |
label-7 | Accessible name for thumb 7 (multi-thumb mode; takes precedence over labels/label) | — | — |
label-8 | Accessible name for thumb 8 (multi-thumb mode; takes precedence over labels/label) | — | — |
labels | JSON string array of per-thumb accessible names (e.g. ["Low","Mid","High"]; the label-N attribute family takes precedence) | string | — |
large-step | Keyboard large step amount (Shift+arrows / PageUp / PageDown); defaults to 10 × step; each key press emits oas-input + oas-change | string | — |
levels | Stereo 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 | — |
marks | Ticks: 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 reverse | string | Record<string, string | number> | number[] | — |
max | Range | string | 100 |
min | Range | string | 0 |
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, an explicit value acts as a stricter constraint); lower priority than format/formatTooltip channels | string | — |
range | Range 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 array | boolean | — |
readonly | Readonly (independent of disabled): stays focusable and the value still participates in form collection; dragging and keyboard edits are intercepted; not visually dimmed | boolean | — |
reset-value | Double-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-change | string | — |
reverse | Reversed direction: minimum on the right horizontally (track dir="rtl"), at the top vertically; fill/ticks/custom thumb positions mirror accordingly | boolean | — |
scrub | Readout 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 pointers | string | true |
show-input | Show 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-stops | Render tick dots along the track by step (no labels), highlighted where passed; marks take precedence when both exist; dots are not rendered beyond 100 | boolean | — |
show-tooltip | Show a value bubble above the thumb (temporarily shown while dragging; coexists with custom-thumb) | boolean | — |
show-track | Track visibility switch (shown by default); show-track="false" hides the track bar and selection fill (the thumb remains draggable and keyboard operable) | string | true |
size | Three 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 md | string | medium |
start-point | Fill 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 mode | string | — |
step | Step; 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) | string | 1 |
thumb | Thumb 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 round | string | round |
tooltip-always | Keep the value bubble always visible (by default shown while dragging or keyboard-focused) | boolean | — |
tooltip-position | Value bubble direction: top / bottom / left / right; top by default horizontally, right by default vertically; invalid values fall back to the default | string | — |
track | Color 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 track | string | — |
track-color | Track base color: preset semantic names map to theme tokens; any other value is passed through as a CSS color | — | — |
value | Current 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-width | Width of the show-input readout box: plain numbers get px, unit values pass through (written to --oas-slider-value-width); defaults to 72px | string | — |
vertical | Vertical 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 variable | boolean | — |
Property (JS property; see each row for attribute reflection)
| Property | Description | Type | Default |
|---|---|---|---|
levels | Stereo level values { left, right } (normalized 0–1; object assignment reflects to a JSON attribute, clear with null) | { left?: number; right?: number } | string | null | — |
value | Current value: a number for a single thumb, or an array of numbers for multiple thumbs | number | number[] | — |
Events
| Event | Description |
|---|---|
oas-change | Committed on release, detail: { value } (single number; [lo, hi] array in range mode) |
oas-input | While dragging / after debounced typing commit, detail: { value } (single number; [lo, hi] array in range mode) |
Slots
| Name | Description |
|---|---|
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 Variable | Description | Default |
|---|---|---|
--oas-glass-refraction | Liquid-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-image | Color-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.