Slider

A slider lets the user choose a value from within a continuous range by moving a thumb along a track. It is one of the most commonly re-implemented widgets — yet the platform already ships one. Reach for a native <input type="range"> first: it is keyboard-operable, exposes its value to assistive technology, and respects user preferences with no scripting at all.

Build the ARIA slider below only when the native control genuinely can’t meet the need — for example a non-linear scale, a custom two-handle range, or visual requirements the native thumb can’t express. When you do, you take on the full WAI-ARIA Authoring Practices slider contract: a focusable role="slider" thumb, the aria-valuemin / aria-valuemax / aria-valuenow trio, an accessible name, and the keyboard model documented here. The page is a reference implementation: the markup is authored statically and slider.js enhances it.

Live demo

Tab to the thumb, then use the arrow keys to nudge the value by one, Page Up / Page Down for a larger jump, and Home / End for the ends of the range. You can also drag the thumb with a pointer. The current value is shown both by the thumb’s position and by the text readout beside the label.

Volume: 40%

When to use

Prefer the native control first

  • For a single value from a numeric range, use <input type="range"> with a real <label> — it is keyboard- and screen-reader-complete for free.
  • Pair any range input with a visible readout (and an explicit step) so the value is perceivable without dragging.
  • Build this ARIA slider only when you need a non-linear scale, a custom thumb, a multi-handle range, or behaviour the native control can’t express — and budget for the keyboard model below.
  • Whatever you choose, the control must carry an accessible name and announce its current value as it changes.

Markup

Author the thumb with its full ARIA value contract already in place, then let slider.js manage interaction. With scripting off, the thumb is still a named, value-bearing control — the script only adds keyboard and pointer behaviour and keeps the position, fill, and readout in sync.

slider.html
<div class="ewa-slider" data-slider>
  <p class="ewa-slider__label" id="vol-label">Volume:
    <span class="ewa-slider__readout" id="vol-readout">40%</span>
  </p>
  <div class="ewa-slider__track">
    <div class="ewa-slider__fill" aria-hidden="true"></div>
    <div class="ewa-slider__thumb" role="slider" tabindex="0"
         aria-valuemin="0" aria-valuemax="100" aria-valuenow="40"
         aria-label="Volume" data-readout="vol-readout"></div>
  </div>
</div>

Keyboard interactions

Focus rests on the thumb. Every key acts directly on the value and the change is announced through aria-valuenow, so a keyboard or screen-reader user can set the value precisely without a pointer.

Keyboard interactions (focus remains on the thumb)
Key Action
Tab Moves focus to the slider thumb.
Right Arrow / Up Arrow Increases the value by one step.
Left Arrow / Down Arrow Decreases the value by one step.
Page Up Increases the value by a larger step (10).
Page Down Decreases the value by a larger step (10).
Home Sets the value to the minimum.
End Sets the value to the maximum.

ARIA roles, states, and properties

The thumb owns the slider role and the whole value contract. The minimum, maximum, and current value are required; add aria-valuetext when a bare number would not be meaningful (for example a label like “Medium” or “$20–$40”).

ARIA attributes and where they live
Attribute On Purpose
role="slider" Thumb Identifies the focusable element as a slider control.
tabindex="0" Thumb Puts the thumb in the tab order so it is keyboard-focusable.
aria-valuemin Thumb The lowest value the slider can take.
aria-valuemax Thumb The highest value the slider can take.
aria-valuenow Thumb The current value; updated on every change so AT announces it.
aria-valuetext Thumb A human-readable value to announce when the number alone is not meaningful.
aria-label / aria-labelledby Thumb Gives the slider an accessible name (here, “Volume”).

Common mistakes

Pitfalls to avoid

  • Hiding the current value. Provide a visible text readout of the value; the thumb position alone is hard to read precisely and useless to a screen-reader user if aria-valuenow is stale.
  • Reinventing the wheel. Check whether a native <input type="range"> meets the need first — it is accessible by default and far less code to maintain.
  • Failing non-text contrast. The thumb and track are graphical UI components: ensure they meet a 3:1 contrast ratio against adjacent colours (SC 1.4.11), and remap to system colours under forced-colors mode.
  • Forgetting the accessible name. A slider with no aria-label or associated label is announced only as “slider” with no indication of what it controls.
  • Skipping aria-valuetext when the number is meaningless. For ranges like price tiers or sizes, a bare number leaves the user guessing — announce the human-readable value instead.