Standards · ARIA

Role Widget

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 to aria-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-valuenow on 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>