Slider
A slider sets an approximate number, or a range, by dragging a handle along a scale.
<tk-slider label="Volume" value="60" show-value></tk-slider>
Anatomy
| Part | What it is |
|---|---|
tk-slider |
the element; one Tab stop per handle |
| track | the full scale |
| filled range | from the start to the handle, or between the two handles in a range |
| handle | the round grip you drag; the slider itself, for screen readers |
| value bubble | an optional readout above the handle while you drag or focus it (show-value) |
| min and max labels | optional labels at the ends (show-min-max) |
| tick marks | optional marks at each step (marks) |
Clicking the track moves the nearest handle there. The slider has no visible label: put
one above it, and set label to the same words.
Range
<tk-slider range label="Price" min="0" max="500" step="10" value-start="100" value-end="300" show-value></tk-slider>
rangeadds a second handle. Read the bounds fromvalue-startandvalue-end.- The handles can't cross.
min-gapkeeps them at least that many units apart. - Each handle is its own Tab stop. Screen readers hear them as "Price (minimum)" and "Price (maximum)".
- For important ranges, also offer two number inputs. Two-handle sliders work unevenly with screen readers.
Scale and readout
<tk-slider label="Brightness" value="40" value-format="percent" show-min-max></tk-slider> <tk-slider label="Rating" min="1" max="5" value="3" marks show-value></tk-slider>
min,max, andstepset the scale. Values clamp to it and snap tostep, with or without tick marks.value-format="percent"shows the value as a percentage, in the bubble, the end labels, and for screen readers.marksshows a tick at eachstep. Use it for a few steps, not a long scale.- For currency or units, set the
formatproperty to a function; it overridesvalue-format:
<tk-slider id="budget" label="Budget" max="1000" step="50" show-value></tk-slider>
<script>
document.querySelector('#budget').format = (v) => `$${v}`;
</script>Sizes
<tk-slider label="Medium slider" value="50"></tk-slider> <tk-slider label="Small slider" size="small" value="50"></tk-slider>
size |
Track | Handle | Height |
|---|---|---|---|
medium (default) |
10px | 18px | 24px |
small |
4px | 12px | 24px |
Both sizes are 24px tall, and each handle has a 24px target, so a slider fits a dense row without extra padding.
States
<tk-slider label="Bass" value="30" disabled></tk-slider>
The handle grows while you drag it. Keyboard focus shows a ring around the handle.
disabled: the slider is dimmed, can't be focused or changed, and isn't submitted.
When to use
- Use a slider for an approximate value with instant feedback, such as volume or brightness.
- Use
rangefor a low and a high bound, such as a price range. - Use a
Number input for an exact number, a very large or very small range, or when people need to type. Pair one with the slider when they need both. - Use a
Progress bar to show progress. A slider is for input. - Don't use a slider for dates or other non-numeric values.
Content
- Make the label the value being set, such as "Volume", not an instruction such as "Drag to set volume".
- Keep min on the leading side and max on the trailing side. In right-to-left layouts, mirror it.
- Format values the way people read them: a percentage, a currency, a unit.
Do / Don't
| ✅ Do | ❌ Don't |
|---|---|
| Use a slider for an approximate value with instant feedback | Collect an exact number with it; use a number input |
| Label it with what it sets: "Volume" | Label it with an instruction: "Drag to adjust" |
| Pair it with number inputs for exact or important values | Rely on a two-handle slider alone for screen reader users |
| Use a progress bar to show progress | Use a slider to show progress |
| Use it for numbers | Use it for dates or other non-numeric values |
Related
Number input : an exact number, typed.Progress bar : shows progress; looks similar, but read-only.Input : other text and number fields.
API
Attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
label |
string | the accessible name, required; range handles add "(minimum)" and "(maximum)" | |
value |
number | 0 |
the value, single mode |
range |
boolean | false |
two handles instead of one |
value-start |
number | 0 |
the low handle, range mode |
value-end |
number | 100 |
the high handle, range mode |
min |
number | 0 |
the start of the scale |
max |
number | 100 |
the end of the scale |
step |
number | 1 |
the increment for keys and dragging |
min-gap |
number | 0 |
range mode: the smallest distance between the handles |
size |
medium | small |
medium |
the track and handle size |
show-value |
boolean | false |
the value bubble while dragging or focused |
value-format |
number | percent |
number |
how values are written |
show-min-max |
boolean | false |
labels at both ends |
marks |
boolean | false |
tick marks at each step |
disabled |
boolean | false |
not focusable, not changeable, left out of the form |
name |
string | the form field name |
Properties
| Property | Type | What it does |
|---|---|---|
format |
(value: number) => string |
writes the value for the bubble, end labels, and screen readers; overrides value-format |
Events
input and change fire together each time the user moves a handle by a step, by
dragging or with keys; not when your code sets a value. Read value, or value-start and
value-end. form.reset() restores the initial values without firing either.
Form value
A single slider submits value under name. A range submits two fields:
{name}-start and {name}-end.
Methods
focus() moves focus to the handle, or the low handle in a range.
Tokens
| Part | Token |
|---|---|
| track | surface/sunken |
| filled range | fill/accent; disabled fill/disabled |
| handle | surface/default + border/selected border |
| focus ring | border/accent/focus |
| value bubble | surface/inverse + text/inverse, radius-8 |
| min and max labels, tick marks | text/secondary |
The track, filled range, and handle use radius-full. End labels are Body Small. Values per
theme:
Accessibility
Built in:
- Each handle is a
role="slider"with its value, min, max, and a readable value text. - In a range, each handle's limits follow the other handle, and each has its own name.
- The full slider keyboard, below. Focus shows only for keyboard users and is never hidden.
- Each handle has a 24 × 24px target in both sizes.
- The track, fill, and handle edges are at least 3:1 in every theme.
- With reduced motion, the handle still moves, without the grow animation.
Your part:
- Set
label, and show the same words as a visible label. - For exact values, or important ranges, add number inputs as well.
| Key | Action |
|---|---|
Tab |
moves focus to the next handle |
→ / ↑ |
adds one step |
← / ↓ |
subtracts one step |
Shift + arrow, Page Up / Page Down |
a big step: a tenth of the scale, at least one step |
Home / End |
jumps to the lowest or highest value |