Range
A slider for one value, or for an interval with variant="range", rendered as
<input is="root-range" type="range">.
Usage
A single-thumb range:
<input is="root-range" type="range" data-label="Volume" min="0" max="100" step="1" value="40"
data-value-format="({value}%)" />
A dual-thumb interval range (variant="range"):
<input is="root-range" type="range" variant="range" data-label="Price" min="0" max="100" low="20" high="80"
data-value-format="({low}€ - {high}€)" data-value-decimals="2" />
The field around it
A range has no field box - no frame, no ground, nothing to put padding inside - so what it takes from
Input, Select and Textarea is the composition rather than the skin: the same
data-label, the same required marker, the same hint node under it, at the same steps.
fieldDecorator
builds all of it, which is why the label is data-label and not a label
attribute of its own. It was one, for a while: the one field in the library whose name the decorator never
saw, so a range that asked for a label got a group name for assistive tech and nothing on screen.
<input is="root-range" type="range" data-label="Budget" data-hint="Monthly, before tax" min="0" max="500" value="180" required />
<input is="root-range" type="range" data-label="Budget" data-error="Above the plan limit" data-invalid="true" min="0" max="500" value="480" />
The value in the label
A slider's value is the one thing about it that is invisible: the thumb says roughly where in the interval
it sits, and nothing says what that is in the units the reader cares about.
data-value-format is a template appended to the label - { value} on a single
thumb, { low} and { high} on an interval - and
data-value-decimals how many places each number takes, so a price reads
20.00 where a percentage reads 20.
It renders inside the label, so a screen reader gets the value with the name rather than having to reach the slider to find it.
<input is="root-range" type="range" data-label="Brightness" min="0" max="100" step="5" value="65"
data-value-format="({value}%)" />
<input is="root-range" type="range" variant="range" data-label="Budget" min="0" max="500" low="120" high="380"
data-value-format="({low}€ - {high}€)" data-value-decimals="2" data-hint="Monthly, before tax" />
The interval
variant="range"
overlays a second range input on a shared track, wraps the pair in a
[data-part="range"]
group and paints the fill between the two thumbs. low and high are where they
start, and moving either attribute afterwards moves the thumb: each clamps against the other, so neither
can be dragged - or set - past its partner.
The track fills the row it is in, which is what the [field-wrapper] is for. Left unstyled
that wrapper was an inline, shrink-to-fit <span>, and the group asking it for
inline-size: 100%
got a percentage of a width still being computed: both thumbs are absolutely positioned, so the group's
min-content contribution is zero and the whole interval range collapsed to two thumbs stacked on each
other.
<input is="root-range" type="range" variant="range" data-label="Delivery window" min="8" max="20" step="1" low="10" high="14" data-hint="Hours, 24-hour clock" />
Sizes
data-size
takes small and large; medium is the default and needs no value written. The
step moves the track and the thumb together.
<input is="root-range" type="range" data-size="small" data-label="Small" min="0" max="100" value="30" />
<input is="root-range" type="range" data-label="Medium" min="0" max="100" value="50" />
<input is="root-range" type="range" data-size="large" data-label="Large" min="0" max="100" value="70" />
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
number |
- | Current value (single) |
min |
number |
0 |
Minimum value |
max |
number |
100 |
Maximum value |
step |
number |
1 |
Step increment |
variant |
'range' |
- | Dual-thumb interval range |
low |
number |
min |
Lower bound (range); clamped at high |
high |
number |
max |
Upper bound (range); clamped at low |
data-size |
'small' | 'large' |
medium | Track and thumb scale |
data-label |
string |
- | Label text; also names the group and both thumbs (range) |
data-value-format |
string |
- |
Template appended to the label: { value}, or { low} /
{ high} on a range
|
data-value-decimals |
number |
0 |
Decimal places each number in the template takes |
required |
boolean |
false |
Marks the field required and draws the asterisk |
data-hint |
string |
- | Description shown under the track |
data-error |
string |
- | Error message; falls back to validationMessage |
data-invalid |
'true' |
- | Shows the error instead of the description |
disabled |
boolean |
false |
Disables the range |
Properties
| Property | Type | Description |
|---|---|---|
isRange |
boolean |
Whether this is the dual-thumb variant |
low / high |
number |
The two bounds (range); high is NaN on a single thumb |
Events
| Event | Detail | Description |
|---|---|---|
root-range.input |
{ value } / { low, high } |
Fired on value change |
root-range.change |
{ value } / { low, high } |
Fired when the value is committed |
Extends
HTMLInputElement
- use with <input is="root-range">. In range mode the two native
range inputs are overlaid on a shared track; each keeps role="slider"
and gets its own accessible name (… (minimum)
/ … (maximum)), taken from
data-label, with the group taking the label itself.