Slider
UI pattern
slider role, a descriptive name, and a value within reported limits, and keyboard users can reach it and change its value.A slider's value is a number between a minimum and a maximum, and users change it by dragging the thumb, clicking the track, or pressing the arrow keys.
Build a slider with the native HTML <input type="range"> element whenever you can. Browsers give it the slider role, report its value and limits, and provide keyboard, pointer, and touch operation at no cost. When a design constraint rules out the native input, a generic element can serve as a slider by carrying role="slider" and ARIA value properties, but then keyboard and pointer operation, and every value update, become your responsibility.
A slider is one of several range widgets, which report a value within limits. The others, listed in Related Patterns, either report a value users can't change or set it in a different way.
Note: Some touch-screen assistive technologies can't operate a custom ARIA slider, because their gestures for raising and lowering a value don't yet produce the key events the slider listens for. This is one more reason to prefer <input type="range">. If you build a custom slider, test it with assistive technology on touch devices before you ship it.
When to Use
Use a slider when:
- Users choose a value from a known range, such as a volume, brightness, or zoom level.
- The value's position in the range matters more to users than the exact number.
Do not use a slider when:
- Users need to enter an exact number they already know, such as a quantity or a year. Use a spin button or a text input instead.
- The value is status the user can't change, such as disk usage or download progress. Use a meter or a progress bar instead.
- Users set two related values in one range, such as a minimum and a maximum price. Use a multi-thumb slider instead.
- The choices are a short list of named options rather than points on a scale. Use a radio group or a
<select>element instead.
Examples
Code in this section is meant to demonstrate techniques rather than requirements and lacks features needed in a production application.
Native HTML Range Slider
The <input type="range"> element exposes the slider role, reports its value, min, and max to assistive technology, joins the tab order, and responds to the arrow keys, Home, End, and pointer and touch input, all without ARIA or code. The step attribute sets how far each arrow key press moves the value, the browser keeps the value inside the range, and the <label> gives the slider its accessible name.
Native slider HTML
<label for="volume">Volume</label>
<input
type="range"
id="volume"
name="volume"
min="0"
max="100"
step="5"
value="50"
/>Custom ARIA Slider
The slider role goes on the thumb, the element users focus and move. aria-valuemin, aria-valuemax, and aria-valuenow report the range and the current value, aria-labelledby points to the visible label, and tabindex="0" puts the thumb in the tab order.
Script does the rest. Every change, from a key or the pointer, goes through setValue(), which snaps the value to the step, clamps it to the range, and updates aria-valuenow and the thumb's position together. Both handlers ignore input while aria-disabled="true" is set. CSS positions the thumb on the track, and touch-action: none on the track lets a drag on a touch screen move the thumb rather than scroll the page.
Custom slider HTML
<span id="volume-label">Volume</span>
<div class="slider-track" data-step="5" data-page-step="20">
<div
class="slider-thumb"
role="slider"
tabindex="0"
aria-labelledby="volume-label"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
></div>
</div>Custom slider JavaScript
class CustomSlider {
constructor(thumb) {
this.thumb = thumb;
this.track = thumb.parentElement;
this.min = Number(thumb.getAttribute("aria-valuemin"));
this.max = Number(thumb.getAttribute("aria-valuemax"));
this.step = Number(this.track.dataset.step) || 1;
this.pageStep = Number(this.track.dataset.pageStep) || this.step * 10;
thumb.addEventListener("keydown", (event) => this.onKeydown(event));
this.track.addEventListener(
"pointerdown",
(event) => this.onPointerdown(event)
);
this.track.addEventListener("pointermove", (event) => {
if (this.track.hasPointerCapture(event.pointerId)) this.moveTo(event);
});
this.setValue(this.value);
}
get value() {
return Number(this.thumb.getAttribute("aria-valuenow"));
}
get disabled() {
return this.thumb.getAttribute("aria-disabled") === "true";
}
// Every change comes through here: snap to the step, clamp to the range,
// then update the reported value and the thumb's position together
setValue(value) {
const steps = Math.round((value - this.min) / this.step);
const snapped = this.min + steps * this.step;
const clamped = Math.min(this.max, Math.max(this.min, snapped));
this.thumb.setAttribute("aria-valuenow", String(clamped));
const ratio = (clamped - this.min) / (this.max - this.min);
this.thumb.style.left = `${ratio * 100}%`;
}
onKeydown(event) {
if (this.disabled) return;
const changes = {
ArrowRight: this.step,
ArrowUp: this.step,
ArrowLeft: -this.step,
ArrowDown: -this.step,
PageUp: this.pageStep,
PageDown: -this.pageStep,
};
if (event.key in changes) this.setValue(this.value + changes[event.key]);
else if (event.key === "Home") this.setValue(this.min);
else if (event.key === "End") this.setValue(this.max);
else return;
// Keep the page from scrolling on the same key press
event.preventDefault();
}
onPointerdown(event) {
if (this.disabled) return;
// Keep focus on the thumb rather than letting the press move it
event.preventDefault();
this.track.setPointerCapture(event.pointerId);
this.thumb.focus();
this.moveTo(event);
}
moveTo(event) {
const rect = this.track.getBoundingClientRect();
const ratio = (event.clientX - rect.left) / rect.width;
this.setValue(this.min + ratio * (this.max - this.min));
}
}
document
.querySelectorAll('[role="slider"]')
.forEach((thumb) => new CustomSlider(thumb));Structure and Semantics
Assistive technology conveys four things about a slider: its slider role, an accessible name that says what the value is for, its current value, and the range that value sits in. All four belong on the one element users focus and move, which for a custom slider is the thumb.
A native <input type="range"> conveys all of these through HTML. Its min, max, and value attributes set the range and the value, the browser keeps the value inside the range and on a step, and an associated <label> names it. Don't add aria-valuemin, aria-valuemax, or aria-valuenow to a native slider. aria-valuetext is the exception: it has no native counterpart, so it's allowed on either kind.
A custom slider built from a generic element needs ARIA for each of these:
| Attribute | How to use |
|---|---|
role | Set to "slider" on the thumb of a custom slider. An <input type="range"> has this role implicitly. |
aria-valuenow | Required. Set to the current value, and update it every time the value changes. |
aria-valuemin | Set to the lowest allowed value. Defaults to 0 when omitted, but set it anyway so the range is stated, not assumed. |
aria-valuemax | Set to the highest allowed value. Defaults to 100 when omitted, but set it anyway so the range is stated, not assumed. |
aria-valuetext | Optional. Set to a readable form of the value, such as "February" for 2, when the number alone isn't meaningful. |
aria-orientation | Set to "vertical" on a vertical slider. The default is "horizontal". |
aria-disabled | Set to "true" to disable a custom slider. A native slider uses the disabled attribute instead. |
tabindex | Set to "0" so a custom slider joins the tab order. A native slider is focusable by default. |
The slider role makes everything inside it presentational, so a heading or other element placed inside the thumb loses its role. Keep the visible label and any displayed value outside the thumb, and reference the label with aria-labelledby.
A custom slider also isn't part of a form. To submit its value with the form, make it a form-associated custom element and set its value with ElementInternals.setFormValue(), as the HTML Standard's Form-associated custom elements section describes.
Role
A slider exposes the slider role on the element users focus and move. An <input type="range"> carries the role implicitly and needs no role attribute. A custom slider puts role="slider" on the thumb, not on the track that contains it, together with the accessible name, the value properties, and the tab stop.
Has the correct role
Reported as: Element has incorrect role
A slider must expose the slider role so assistive technology reports it as holding a value users can change.
When a custom slider is built from a <div> without the role, or carries a different one, assistive technology presents it as plain content or as the wrong kind of control. Users aren't told that it has a value or that the arrow keys change it, and its value properties go unreported.
Use a native <input type="range">, or add role="slider" to the thumb of a custom slider.
Severity: Critical
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
Applies role to the correct element
Reported as: Incorrect root element
Sanity check. Evinced checks that the slider role sits on the element users focus and move, not on an element around it or inside it. This check runs on every UI pattern, not only on sliders.
A slider should carry the slider role on the thumb users focus and move, not on the track around it or an element inside it.
When the role sits on the track while the tab stop and key handling sit on the thumb, assistive technology reports the focused thumb, which has no role or value. Users land on the slider and aren't told what it is or where it's set, even though role="slider" is in the markup.
Put the role, the accessible name, the value properties, the tab stop, and the key handling on the thumb. Keep the track a plain container for layout and pointer input.
Accessibility Label
A slider's accessible name says what the value controls, such as "Volume" or "Brightness". It doesn't include the current value. Assistive technology reports the value alongside the name, and a name that included it would be wrong as soon as the value changed.
A native slider takes its name from an associated <label>, either by the for attribute, as in the Native HTML Range Slider example, or by wrapping the input. A custom slider takes its name from aria-labelledby pointing to visible text, as in the Custom ARIA Slider example, or from aria-label when there's no visible label. The following example shows the two ways the examples above don't.
<!-- Native: the label wraps the input -->
<label>
Volume
<input type="range" min="0" max="100" value="50" />
</label>
<!-- Custom: no visible label, so aria-label names the slider -->
<div role="slider" tabindex="0" aria-label="Volume" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50"></div>Names a container that needs one
Reported as: Missing contextual labeling
A slider must have an accessible name that says what its value is for.
When a slider has no accessible name, assistive technology reports only its role and value, so screen reader users hear "slider, 50" with no way to know whether it sets the volume, the brightness, or something else. The visible text beside it helps sighted users only, and voice control users have no name to speak.
Associate a <label> with a native slider. For a custom slider, point aria-labelledby at the visible label, and use aria-label only when there's no visible text to reference.
Severity: Serious
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 1.3.1 Info and Relationships (A) | Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text. |
| EN 301 549 | 9.1.3.1 Info and Relationships | Same as the WCAG text. |
aria-valuetext
When a slider's number doesn't say what the value means, aria-valuetext gives assistive technology a readable form of it, such as a month name, a temperature with its unit, or the label of a point on a rating scale. Assistive technology reports the text in place of the number, so the text has to change every time the value does. It's allowed on a native <input type="range"> as well as on a custom slider.
The following example gives a month slider the name of each month as its value text.
<label for="month">Month</label>
<input type="range" id="month" min="1" max="12" value="2" aria-valuetext="February" />
<script>
const month = document.getElementById("month");
month.addEventListener("input", () => {
const date = new Date(2000, month.valueAsNumber - 1);
month.setAttribute("aria-valuetext", date.toLocaleString("en", { month: "long" }));
});
</script>Uses value text to add meaning
Reported as: Meaningful aria-valuetext
A slider's aria-valuetext should say something its number doesn't.
When aria-valuetext repeats the value, such as "50" for a value of 50, screen reader users hear nothing the number didn't already tell them. The text also replaces the number in what assistive technology reports, so if it isn't updated with the value, screen reader users hear a value the slider no longer holds.
Leave aria-valuetext off when the number speaks for itself. When the number needs explaining, set text that explains it, and update it in the same place as the value.
Severity: Minor
Values
A slider reports its current value and the limits of its range, so users know where it's set and how far it can go. Assistive technology often presents the value as a percentage of the range, so the three numbers have to agree with each other and with what's on screen.
Leaves native values to HTML
Reported as: Avoid ARIA values on native inputs
A native <input type="range"> must not also carry aria-valuenow, aria-valuemin, or aria-valuemax.
When a native slider has ARIA value properties alongside its own value, min, and max, the two can disagree. The browser updates value as the user moves the slider, while the ARIA properties keep whatever code last wrote, so screen reader users can hear a value the slider no longer holds.
Remove the ARIA value properties and let value, min, and max report the slider's state. Keep aria-valuetext if the number needs explaining, since it has no native counterpart.
Severity: Critical
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
Orders its limits low to high
Reported as: Min value is greater than the max value
A slider's minimum must be lower than its maximum.
When the minimum is greater than the maximum, assistive technology can't place the value within the range. Screen reader users hear a bare number, or a negative percentage, with no sense of where it falls, and Home and End no longer have a clear meaning.
Sort the two limits before declaring them, including limits taken from data, so the smaller one is always the minimum. Declare a descending scale low to high too, and handle its direction in the presentation.
Severity: Critical
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
Reports its value and its limits
Reported as: Missing range attributes
A slider must report its current value and the limits of its range to assistive technology.
When a custom slider shows its value only through the position of the thumb and never sets aria-valuenow, screen reader users learn they're on a slider but not what it reads. Missing limits fail more quietly: assistive technology assumes a range of 0 to 100, so screen reader users can hear a value of 4 on a scale of 1 to 7 as 4 percent.
Set aria-valuenow on a custom slider, and update it in the same code that moves the thumb. Declare aria-valuemin and aria-valuemax whenever the range isn't 0 to 100, and set them anyway when it is, so the markup states the range rather than relying on the defaults. A native <input type="range"> reports all three from its value, min, and max.
Severity: Critical
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
Spans more than a single value
Reported as: Range has equal min and max values
A slider's range must have room for more than one value, with a maximum above its minimum.
When the minimum and maximum are equal, such as a price filter whose results all cost the same, the slider can hold only one value. Users can press keys or drag the thumb with no effect, and they can't tell a slider fixed at one value from one that has stopped responding.
Check that the limits differ before rendering the slider. When they don't, show the single value as text, or disable the slider and say why.
Severity: Critical
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
aria-invalid
A slider clamps its value at each end of its range, and a native <input type="range"> does this on its own, so aria-invalid has little to do on a slider. When the value does fall outside the range, which is itself an error, aria-invalid="true" reports it, and it's removed once the value is back in range.
Flags invalid only when out of range
Reported as: False aria-invalid value
A slider must not report a value inside its range as invalid.
When aria-invalid="true" stays on a slider after its value returns to the range, or is written into the markup as a hook for error styling, screen reader users are told a correct value is wrong. They may keep adjusting a value that was fine, or abandon a form they completed correctly.
Set aria-invalid from the current value each time it changes: true only while the value is outside the range, and removed otherwise. Drive error styling from a class, not from the attribute.
Severity: Serious
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
Keeps the value within its bounds
Reported as: Value out of range
A slider's reported value must sit at or between its minimum and maximum.
When the value comes from data with a different range, or the limits change without the value following, the slider reports a value its own range can't contain. Screen reader users may hear 120 percent on a scale that ends at 100, and stepping from a value outside the range behaves unpredictably.
Clamp the value to the limits whenever the value or the limits change, and set all three from the same source. A native <input type="range"> clamps its value for you.
Severity: Serious
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
Disabled
A disabled slider reports its disabled state in one way, suited to how it's built. A native slider uses the disabled attribute, which also removes it from the tab order and blocks input. A custom slider uses aria-disabled="true", which only reports the state, so code has to ignore key and pointer input and manage the tab stop.
The following example shows the correct attribute for each kind of slider.
<!-- Native: use the disabled attribute -->
<input type="range" id="volume" min="0" max="100" value="50" disabled />
<!-- Not this: aria-disabled on a native slider -->
<input type="range" id="volume" min="0" max="100" value="50" aria-disabled="true" />
<!-- Custom: use aria-disabled, and take it out of the tab order -->
<div role="slider" tabindex="-1" aria-disabled="true" aria-labelledby="volume-label" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50"></div>Avoids conflicting disabled states
Reported as: Conflicting disabled values
A slider must have a single, consistent disabled state.
When a slider sets its disabled state two ways and the values disagree, such as the disabled attribute alongside aria-disabled="false", assistive technology may report a state the browser doesn't enforce. Users can't tell whether they're able to change the value.
Set the disabled state once: the disabled attribute on a native slider, or aria-disabled on a custom one, never both.
Severity: Serious
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
Uses aria-disabled rather than disabled
Reported as: Element does not support the disabled attribute
A custom slider must convey its disabled state with aria-disabled, not the disabled attribute.
When disabled is set on the <div> or <span> behind a custom slider, the browser ignores it. The slider stays in the accessibility tree as an ordinary, available control, so users are told they can change a value the design means to be locked, even when styling grays it out.
Set aria-disabled="true" instead, and ignore key and pointer input in code while it's set. When a native <input type="range"> would do the job, switch to it, and its disabled attribute handles the state, the tab order, and input.
Severity: Serious
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
Disables only elements that support it
Reported as: Element type does not support disabled state
An element in a slider must carry disabled or aria-disabled only when its role supports a disabled state.
When the state sits on an element whose role has none, such as a wrapper, a list item or a heading, assistive technology may drop it or report it on something users can't operate, while the control that really is unavailable is still reported as available.
Remove the attribute from that element, and set the disabled state on the control itself, using an element or role that supports it, such as a native <button>.
Severity: Serious
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
Relationships
A slider is a single element that owns nothing. Its content is presentational, so a visible label, a displayed value, or tick marks sit outside it and relate to it by reference. aria-labelledby points to the label, and aria-describedby can point to supporting text, such as the units the value is measured in. A native slider can take its tick marks from a <datalist> element named by its list attribute.
aria-owns
A slider has no reason to use aria-owns.
Avoids aria-owns
Reported as: Avoid aria-owns
General check. Evinced checks that the slider doesn't use aria-owns to claim elements elsewhere in the document as its children. This check runs on every UI pattern, not only on sliders.
A slider should not own other elements with aria-owns.
The slider role allows only presentational children, so an owned label, value display, or tick mark becomes presentational too. Depending on the browser, screen reader users can miss the owned content, hear it folded into the slider's name, or hear it twice.
Remove aria-owns from the slider and keep the content outside it. Reference the label with aria-labelledby and any supporting text with aria-describedby.
Operation
With a pointer, users drag the thumb along the track, or click the track to move the thumb to that point. With a keyboard, the Tab key moves focus to the slider and the keys in the following table change its value. Each change updates the value the slider reports: value on a native slider, and aria-valuenow, with aria-valuetext when it's set, on a custom one.
| Key | Function |
|---|---|
| Right Arrow, Up Arrow | Increases the value by one step |
| Left Arrow, Down Arrow | Decreases the value by one step |
| Home | Sets the value to the minimum |
| End | Sets the value to the maximum |
| Page Up (optional) | Increases the value by an amount larger than one step |
| Page Down (optional) | Decreases the value by an amount larger than one step |
A step is the amount one arrow key press changes the value, and it's the same for every press. On a native slider, the step attribute sets it, and a custom slider sets it in code. Reversing the direction, so that the Up Arrow key lowers the value, is acceptable when it makes a particular slider clearer.
A native <input type="range"> provides all of this. A custom slider has to reproduce it in code, with keydown and pointer listeners that change the value through one function, as the Custom ARIA Slider example shows.
Focus Sequence
An enabled slider is in the tab order, with its tab stop on the element that carries the slider role. A native <input type="range"> is focusable on its own, and a custom slider needs tabindex="0" on its thumb.
Reachable by keyboard
Reported as: Keyboard accessible
A slider must be reachable with the Tab key.
When a custom slider is built from a <div> with drag handling but no tabindex, keyboard users can't reach it, so they can't change its value, however correct its role and value properties are.
Use a native <input type="range">, which is focusable on its own, or add tabindex="0" to the thumb of a custom slider.
Severity: Critical
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 2.1.1 Keyboard (A) | All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints. |
| EN 301 549 | 9.2.1.1 Keyboard | Same as the WCAG text. |
| Section 508 | 1194.21(a) | When software is designed to run on a system that has a keyboard, product functions shall be executable from a keyboard where the function itself or the result of performing a function can be discerned textually. |
| 508 Trusted Tester | 2.1.1-keyboard-access, 4.A | All functionality can be accessed and executed using only the keyboard. |
Skips tab order when disabled
Reported as: Disabled element focusable
A slider that presents as disabled should not be in the tab order.
When a disabled slider keeps its tab stop, keyboard users land on a control whose value they can't change. In a form with several disabled controls, those stops add up.
Use the disabled attribute on a native slider, which removes it from the tab order. On a custom slider, set tabindex="-1" while aria-disabled="true" is set, and restore tabindex="0" when it becomes available.
Keeping a disabled custom slider focusable is a recognized alternative, since users can then find it, learn its value, and learn that it's unavailable. If you take that route, expose the disabled state and ignore key input.
Severity: Minor
Element that carries role receives focus
Reported as: Focusable offset
A slider must receive focus on the element that carries the slider role, not on one of its descendants.
When the role sits on the track and focus lands on the thumb inside it, assistive technology reports the thumb, which has no role or value. Users tabbing through the page aren't told they've reached a slider or where it's set.
Put the role and the tab stop on the same element, usually the thumb, and remove focusability from any other part. A native <input type="range"> has one element, so the two can't separate.
Severity: Minor
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 2.1.1 Keyboard (A) | All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints. |
| EN 301 549 | 9.2.1.1 Keyboard | Same as the WCAG text. |
| Section 508 | 1194.21(a) | When software is designed to run on a system that has a keyboard, product functions shall be executable from a keyboard where the function itself or the result of performing a function can be discerned textually. |
| 508 Trusted Tester | 2.1.1-keyboard-access, 4.A | All functionality can be accessed and executed using only the keyboard. |
Context Change
Moving a slider changes only its value. Anything more, such as submitting a form, loading another page, or moving focus, waits for an explicit control such as an Apply button. The exception is a change of context that text before the slider tells users to expect. Every arrow key press and every point of a drag is a change, so a slider can pass through many values before users settle on one.
Keeps context when a value changes
Reported as: Unexpected context change on input
Changing a slider's value must not change the context unless users are told beforehand that it will.
When a value change reloads the page or moves focus, screen reader and screen magnifier users may not notice that the page changed, and keyboard users can't step past the first value they reach. A form that submits partway through can discard what users hadn't finished entering.
Update the page in place and leave focus on the slider. Start submission or navigation from an explicit control, or, when the change of context is intended, say so in text that comes before the slider.
Severity: Serious
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 3.2.2 On Input (A) | Changing the setting of any user interface component does not automatically cause a change of context unless the user has been advised of the behavior before using the component. |
| EN 301 549 | 9.3.2.2 On Input | Same as the WCAG text. |
| Section 508 | 1194.22(n) | When electronic forms are designed to be completed on-line, the form shall allow people using assistive technology to access the information, field elements, and functionality required for completion and submission of the form, including all directions and cues. |
| Section 508 | 1194.21(l) | When electronic forms are used, the form shall allow people using assistive technology to access the information, field elements, and functionality required for completion and submission of the form, including all directions and cues. |
Keyboard Navigation
A slider changes its value from the keyboard in steps, and every change stays inside the range and updates the reported value along with the thumb's position. A custom slider handles the keys in a keydown listener and calls preventDefault() for each key it handles, so the arrow keys, Home, and End don't also scroll the page.
Changes value with the keyboard
Reported as: Slider value unchanged with keyboard
A slider must change its value when the user presses an arrow key.
When a custom slider handles only pointer input, it can take focus and expose its role and value correctly while every key press leaves the value where it was. Setting the value is the slider's only job, so people who don't use a pointer, including many screen reader, switch, and keyboard users, can't use it.
Add a keydown handler that changes the value by one step for each arrow key, and update aria-valuenow with the thumb's position. Better still, use a native <input type="range">, which handles the keys on its own.
Severity: Critical
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 2.1.1 Keyboard (A) | All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints. |
| EN 301 549 | 9.2.1.1 Keyboard | Same as the WCAG text. |
| Section 508 | 1194.21(a) | When software is designed to run on a system that has a keyboard, product functions shall be executable from a keyboard where the function itself or the result of performing a function can be discerned textually. |
| 508 Trusted Tester | 2.1.1-keyboard-access, 4.A | All functionality can be accessed and executed using only the keyboard. |
Keeps the value in range
Reported as: aria-valuenow out of range
A slider's value must stay between its minimum and maximum as the user operates it with the keyboard.
When a key handler adds or subtracts a step without checking the limits, holding an arrow key at either end walks aria-valuenow past the range. Screen reader users hear a value the range can't contain, such as a figure above 100 percent, with no way to tell whether the value or the range is wrong.
Clamp every change to the limits in one function that all the keys share, and write the clamped value to aria-valuenow and the thumb's position together.
Severity: Serious
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 9.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |
Sets the maximum with End
Reported as: Slider does not support End key
A slider must set its value to the maximum when the user presses the End key.
When End isn't handled, it scrolls the page instead. Reaching the top of the range then takes one arrow key press per step, and screen reader users hear every value on the way. Users often settle for a value short of the one they wanted.
Handle End in the same keydown listener as the arrow keys, set the value to the maximum, and call preventDefault() so the page doesn't scroll.
Severity: Minor
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 2.1.1 Keyboard (A) | All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints. |
| EN 301 549 | 9.2.1.1 Keyboard | Same as the WCAG text. |
| Section 508 | 1194.21(a) | When software is designed to run on a system that has a keyboard, product functions shall be executable from a keyboard where the function itself or the result of performing a function can be discerned textually. |
| 508 Trusted Tester | 2.1.1-keyboard-access, 4.A | All functionality can be accessed and executed using only the keyboard. |
Sets the minimum with Home
Reported as: Slider does not support Home key
A slider must set its value to the minimum when the user presses the Home key.
When Home isn't handled, it scrolls the page and leaves the value where it was. On a range of a hundred steps, reaching the bottom takes a hundred key presses, which is impractical for anyone who can't drag the thumb.
Handle Home alongside End and the arrow keys, set the value to the minimum, and call preventDefault() so the page doesn't scroll.
Severity: Minor
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 2.1.1 Keyboard (A) | All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints. |
| EN 301 549 | 9.2.1.1 Keyboard | Same as the WCAG text. |
| Section 508 | 1194.21(a) | When software is designed to run on a system that has a keyboard, product functions shall be executable from a keyboard where the function itself or the result of performing a function can be discerned textually. |
| 508 Trusted Tester | 2.1.1-keyboard-access, 4.A | All functionality can be accessed and executed using only the keyboard. |
Event Listener Type
When script in a slider responds to keys, it listens for keydown or keyup. The keypress event is deprecated, and browsers don't fire it for many keys, including the arrow keys, Home, End and Escape.
Avoids the keypress event
Reported as: Deprecated keypress listener
A slider's key handling should use keydown or keyup, not keypress.
When a handler listens for keypress, keys the browser doesn't send through that event go unanswered, and keyboard users find the slider ignoring keys it's meant to respond to.
Replace each keypress listener with a keydown listener, and read the key from event.key.
Severity: Minor
FAQ
Which WCAG success criteria do the slider issues relate to?
Most relate to 4.1.2 Name, Role, Value: the slider role, reporting the value and its limits, ordering the limits and keeping the value within them, the invalid state, how the disabled state is declared, and leaving native values to HTML. The accessible name relates to 1.3.1 Info and Relationships.
Reaching the slider, taking focus on the element with the role, and changing the value with the arrow keys, Home, and End relate to 2.1.1 Keyboard. Keeping the context when the value changes relates to 3.2.2 On Input. Meaningful value text and keeping a disabled slider out of the tab order map to no WCAG success criterion and are best practices.
Why are some slider issues marked as Critical and others as Minor?
Severity reflects how much an issue gets in users' way. Critical issues stop users outright:
- A slider with no role, value, or limits
- Limits in the wrong order or equal
- ARIA values that contradict a native slider
- A slider keyboard users can't reach or change
Serious issues confuse users though tasks are still possible:
- An unnamed slider
- A wrong invalid or disabled state
- A value outside the range
- A value change that loads a page or submits the form
Minor issues are smaller obstacles:
- Value text that adds nothing
- Missing Home and End keys
- A disabled slider in the tab order
- Focus on an element other than the one with the role
The aria-owns check and the check on where the role sits carry no severity: Evinced reports them as general and sanity checks.
Related Patterns
- Meter: a value within a known range that users can't change
- Progress Bar: the progress of a task, which users can't change
- Spin Button: a value in a range that users can type as well as step
- Multi-Thumb Slider: a slider with two or more thumbs, such as a price range
- Text Input: free entry of an exact value
- Radio Group: a single choice from a short list of named options