Communicating Value and Limits for Range Widgets
ARIA defines roles for four types of range widgets: scrollbar, slider, spinbutton, and meter.
This practice is documented in detail at Communicating Value and Limits for Range Widgets - WAI-ARIA APG . Below we provide additional context specific to our pattern implementations.
Overview
Range widgets allow users to set or view a value within a defined range. ARIA defines roles for four types: slider, spinbutton, scrollbar, and meter. Each requires specific properties to communicate the current value and its limits to assistive technology.
Range Widget Types
| Role | Purpose | User Interaction |
|---|---|---|
| slider | Select a value from a range | Arrow keys, drag |
| spinbutton | Enter/adjust a numeric value | Arrow keys, type |
| scrollbar | Control scroll position | Drag, arrow keys |
| meter | Display a gauge value (read-only) | None (display only) |
Required ARIA Properties
For All Range Widgets
<div
role="slider"
aria-valuenow="50"
aria-valuemin="0"
aria-valuemax="100"
aria-label="Volume"
></div>
| Property | Required | Description |
|---|---|---|
aria-valuenow | Yes | Current value |
aria-valuemin | Yes* | Minimum value (*implicit 0 for meter) |
aria-valuemax | Yes* | Maximum value (*implicit 100 for meter) |
aria-valuetext | No | Human-readable value text |
aria-valuetext for Non-numeric Values
When the value isnโt meaningful as a number:
<!-- Time slider -->
<div
role="slider"
aria-valuenow="120"
aria-valuemin="0"
aria-valuemax="480"
aria-valuetext="2:00 PM"
aria-label="Meeting start time"
></div>
<!-- Priority slider -->
<div
role="slider"
aria-valuenow="2"
aria-valuemin="1"
aria-valuemax="5"
aria-valuetext="Medium priority"
></div>
Native HTML Alternatives
Consider native HTML elements first:
<!-- Native range input -->
<label for="volume">Volume</label>
<input type="range" id="volume" min="0" max="100" value="50" />
<!-- Native number input (spinbutton semantics) -->
<label for="quantity">Quantity</label>
<input type="number" id="quantity" min="1" max="99" value="1" />
<!-- Native meter -->
<label for="disk-usage">Disk usage</label>
<meter id="disk-usage" min="0" max="100" low="33" high="66" optimum="20" value="75">75%</meter>
<!-- Native progress -->
<label for="upload">Upload progress</label>
<progress id="upload" max="100" value="70">70%</progress>
Implementation Tips
Multi-thumb Sliders
For sliders with multiple thumbs (e.g., price range):
<div role="group" aria-label="Price range">
<div
role="slider"
aria-label="Minimum price"
aria-valuenow="20"
aria-valuemin="0"
aria-valuemax="100"
></div>
<div
role="slider"
aria-label="Maximum price"
aria-valuenow="80"
aria-valuemin="0"
aria-valuemax="100"
></div>
</div>
Orientation
Specify orientation for vertical sliders:
<div
role="slider"
aria-orientation="vertical"
aria-valuenow="50"
aria-valuemin="0"
aria-valuemax="100"
></div>
Read-only Meters
Meters are inherently read-only. Use meter role for display-only gauges:
<div
role="meter"
aria-valuenow="75"
aria-valuemin="0"
aria-valuemax="100"
aria-label="Battery level"
>
75%
</div>
Common Pitfalls
Missing valuetext for Complex Values
<!-- Bad: Screen reader announces "50" for a time -->
<div role="slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="480" aria-label="Time"></div>
<!-- Good: Screen reader announces "8:30 AM" -->
<div
role="slider"
aria-valuenow="50"
aria-valuemin="0"
aria-valuemax="480"
aria-valuetext="8:30 AM"
aria-label="Time"
></div>
Inconsistent Min/Max/Now
<!-- Bad: valuenow outside range -->
<div role="slider" aria-valuenow="150" aria-valuemin="0" aria-valuemax="100"></div>
<!-- Good: valuenow within range -->
<div role="slider" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
Using Slider for Read-only Display
<!-- Bad: Slider for display-only value -->
<div role="slider" aria-valuenow="75" aria-readonly="true"></div>
<!-- Good: Meter for display-only gauge -->
<div role="meter" aria-valuenow="75"></div>