rangegroup proposal / Open UI Community Group

Open UI Proposal · Draft

The <rangegroup> element

A proof-of-concept for the proposed native multi-thumb range control. The baseline below renders with no custom CSS (approximates Chromium on macOS as an example for UA styles). Every other example demonstrates a different facet of the component’s API, constraints, and pseudo-element-based stylability. This is a proof-of-concept and the code at the moment is hypothetical.

Foundations

Baseline — native default

Two thumbs with no ::part overrides at all. The component’s built-in defaults aim for the Chromium-on-macOS input[type="range"] look: 16px blue thumbs, a 4px rounded track, and a blue fill between the thumbs.

Baseline price range
Show code

Foundations

Single thumb — group of one

A <rangegroup> with one child range still paints the composite slider: one thumb on the group track, not a hidden wrapper. Fill runs from the group minimum to that thumb.

Volume
Show code

Foundations

Interactive price editor

Two-way binding between the component values and number inputs is author JavaScript — not a native reference API or built-in sibling fields. Linked value fields belong with a general data-binding / invoker discussion (#1459) and must also work for a plain input type=range. Drag the handles to update the fields, or type in the fields to move the handles.

Interactive price range
Show code

Foundations

Datalist integration

Pair the component with a <datalist> to snap values to discrete options. The component also enforces a minimum distance of 25 between handles via stepbetween="25".

Rating range
Show code

Constraints and state

Stepbetween distance

stepbetween="10" enforces a minimum distance between adjacent handles, so they can never collide.

Stepbetween example
Show code

Constraints and state

Per-thumb constraints

Each thumb can have its own min and max. The thumb’s movement is restricted to the tighter of its own bounds and the overall component’s bounds.

Thumb constraints
Show code

Constraints and state

Parent override constraints

If a thumb’s bounds exceed the component’s range, the component clamps them. Here the track is 100–200 but the thumbs try to go 0–300.

Parent override constraints
Show code

Constraints and state

Multi-handle constraints

Three handles where the middle one is constrained to a small central zone (30–70), while the outer handles have full range and can push it.

Multi-handle constraints
Show code

Constraints and state

Fully disabled group

The disabled attribute disables the whole control. All thumbs become non-interactive and are removed from the tab order.

Fully disabled group
Show code

Constraints and state

Mixed disabled state

Individual thumbs can be disabled while the rest remain interactive. The button toggles the group-level disabled state to show that individual disabled flags persist on re-enable.

Mixed disabled
Group disabled: false
Show code

Interaction modes

Interaction mode (working name)

Compare endpoint-oriented vs range-oriented pointer behavior. The attribute interaction with keywords endpoints (default) and range is a working name for Open UI bikeshed on #1460 — not a committed HTML API. Do not use draggable. In range mode, pressing anywhere between two thumbs drags that interval and keeps its width; pressing outside it still moves the nearest thumb, and a press without a drag moves nothing. It works with any thumb count — with three or more, the pointer picks which segment moves (see the segment-drag examples further down).

interaction (bikeshed)
Clip in and out points

Show code

Interaction modes

Video timeline trim

Drag the selected clip to slide in and out together while keeping duration. The in/out handles still trim each end. interaction="range" is a working name pending bikeshed on #1460.

Clip in and out

Show code

Interaction modes

Meeting duration slot

A one-hour meeting on a workday calendar. Drag the block to a free slot without changing its length; the handles still resize. Busy times are shown behind the track. interaction="range" is a working name pending bikeshed on #1460.

Standup
Design review
Meeting time

Show code

Three-plus thumb patterns

Crossfade overlap editor

A 3-thumb pattern modeled on a DAW crossfade. The outer thumbs set when Track A starts fading out and when Track B reaches full volume; the middle thumb biases the crossover point that determines which track dominates the overlap.

Track A
Track B
Crossfade overlap editor
Start 2.0s
End 7.8s
Overlap 5.8s
A / B bias 50 / 50
Show code

Three-plus thumb patterns

Opening hours selector

Four handles define morning and afternoon shifts on a single 8 AM–10 PM timeline. The datalist provides hourly tick labels with half-hour granularity.

Opening hours
Morning shift 9:00 AM – 12:00 PM
Afternoon shift 1:00 PM – 5:00 PM
Show code

Three-plus thumb patterns

Opening hours selector (segment drag)

The same four-handle timeline with interaction="range". Pressing inside a shift drags that shift as a block: both of its bounding thumbs move together and the duration stays fixed, while the other two thumbs stay put. With more than two thumbs the pointer position is what decides which interval moves — the case the explainer previously called ambiguous. Presses outside every segment still move the nearest thumb, and a dragged shift is clamped by its neighbours and by stepbetween.

Opening hours, draggable shifts
Morning shift 9:00 AM – 12:00 PM
Afternoon shift 1:00 PM – 5:00 PM
Show code

Three-plus thumb patterns

Multi-handle temperature

Three handles set boundaries for cold / mild / warm / hot zones, each segment rendered in its own colour and each thumb with a matching glow.

Multi-handle temperature
Cold -100° to -50°
Mild -50° to 0°
Warm 0° to 50°
Hot 50° to 100°
Show code

Three-plus thumb patterns

Three-handle process flow

Three handles and styled ticks represent the boundaries between phases in a process. Each major tick gets its own colour, signaling the phase it marks.

Process flow
Show code

Three-plus thumb patterns

Budget allocator

A complete visual transformation. Three thumbs split a 0–100 range into four colored budget bars, with category labels anchored to each segment via CSS Anchor Positioning. An aria-live region announces changes for assistive tech.

Budget allocator
Show code

Three-plus thumb patterns

Budget allocator (segment drag)

The same three-thumb split with interaction="range". Dragging one of the two interior bars shifts its share left or right without resizing it: the two thumbs bounding that bar move together, the categories on either side absorb the change, and the outer thumbs stay where they are. The first and last bars have only one thumb, so pressing there still moves that nearest thumb.

Budget allocator with draggable shares
Show code

Creative styling

Floating anchored tooltips

Invisible handles plus CSS Anchor Positioning makes external tooltips read as the draggable thumbs. The visible “handle” pills are just anchored DIVs.

Floating tooltips
Show code

Creative styling

Classic OS look

Heavy custom styling on all parts to recreate a classic Win-style slider, with anchored tooltips.

Classic look
Show code

Creative styling

Custom tick styling

Individual ticks and tick labels can be styled via CSS Parts. The 50% tick is highlighted with a different colour and height.

Custom tick styling
Show code

Creative styling

Histogram price filter

An Airbnb-style price filter. The histogram behind the slider previews item distribution; bars inside the active range light up in the brand accent. Pill thumbs with grip lines carry floating price tags via CSS Anchor Positioning.

Price range
$0 – $1,000 1,247items match
Show code

Creative styling

Star rating filter

A two-thumb 1–5 star rating filter. The five stars below the track act as labels and snap targets via list — stars inside the selected range fill in gold, the rest stay hollow.

Star rating filter
3 stars 5 stars
Show code

Creative styling

Color-stop gradient editor

Three color swatches author a linear-gradient(...) string. Each thumb's position becomes a gradient stop in the preview above and in the slider's own segments below. The CSS string updates live; preset chips drive the setRangeValue API.

Color stop positions
Presets
Show code

Creative styling

Styled timeline

Ticks dressed up as milestones on a project timeline. The start, middle, and end ticks are promoted with a distinct colour and height.

Styled timeline
Show code

Creative styling

Wavy track shape

The track is repainted as a wave and every thumb rides the curve — with no changes to the component. Each thumb exposes its position as --thumb-left (the proposed --slider-thumb-position), so an opt-in stylesheet can drive offset-path / offset-distance. Dragging and keyboard control are unchanged.

Wavy track values
Show code

Creative styling

Circular track shape

A two-thumb circular range dial, built entirely with opt-in CSS. Thumbs orbit the ring via offset-path + offset-distance: var(--thumb-left), and the filled arc is a conic-gradient driven by the segment’s exposed --segment-left / --segment-width. A tiny opt-in script maps pointer movement to angle so dragging feels truly circular. The value chips are purely presentational and intentionally omitted from the code sample. The component itself is unchanged.

Circular range dial
Show code

JavaScript API

Programmatic interaction

Use the component’s public methods and properties to get and set values from script.

JS API interaction
Show code

JavaScript API

Linked value fields (author JS)

Telecon outcome on #1459: linking a number field to a slider is not a <rangegroup>-only feature and must not be solved by putting number inputs in the group shadow tree. Both demos below use the same author-space input listeners — one against a native range, one against a single-thumb <range-group>.

Native input type=range

One-thumb <range-group>

Volume
Show code

JavaScript API

Add & remove thumbs (gradient builder)

A live gradient editor where each thumb is a color stop. addThumb(value, options) and removeThumb(index) grow and shrink the control on demand — new handles are real <input type="range"> elements, so they stay keyboard-accessible and form-friendly.

Gradient color stops
Show code