slider
Marks an element as an input that selects a value from a range. Use <input type="range"> first; only reach for role="slider" when you need a custom track — for example a two-thumb range picker, which native does not support.
When to use
Use <input type="range">. Native gives you keyboard support, touch gestures, tick marks via <datalist>, and a value that submits with the form.
role="slider" is for custom controls native cannot express:
- Two-thumb range pickers (price min/max).
- Non-linear scales (logarithmic, stepped colour pickers).
- Sliders styled in a way the native input cannot achieve in a given design system.
Keyboard + focus contract
Per the APG slider pattern:
- Tab moves focus to the slider thumb.
- Right/Up arrow increases the value by one step; Left/Down decreases.
- Page Up / Page Down jump by a larger increment (typically 10%).
- Home jumps to
aria-valuemin; End jumps toaria-valuemax.
You MUST set aria-valuenow, aria-valuemin, and aria-valuemax. If the numeric value is not self-explanatory (“3” — three what?), add aria-valuetext="3 stars" so screen readers announce the meaningful version.
For two-thumb sliders, render two separate role="slider" elements, each with its own min/max reflecting the other thumb’s position.
Common failures
- Missing
aria-valuenowon first render. The slider has no announced value. - Slider value not updated after drag. Screen readers report the original value forever.
- A “0 to 100” volume slider with no
aria-valuetext— the user hears “47” with no unit. - Keyboard step too coarse. A 0-100 slider that jumps in increments of 10 means screen-reader users cannot pick 53.
- Two-thumb sliders rendered as a single element with
aria-valuetext="20 to 80". The user cannot adjust either bound independently.
Example
<!-- Preferred -->
<label for="vol">Volume</label>
<input id="vol" type="range" min="0" max="100" value="50">
<!-- Custom slider -->
<div id="brightnessLabel">Brightness</div>
<div
role="slider"
tabindex="0"
aria-labelledby="brightnessLabel"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="60"
aria-valuetext="60 percent"
></div>