Accessible Sliders
This page shows two examples of a slider: an HTML5 one implemented with <input type="range">
and
an ARIA one using the slider
role and fair amount of JavaScript. While the latter solution
is accessible on both desktop and mobile, it works so differently than the native one in mobile devices due
to JavaScript limitations, and is a great example of "just because you can so something, it doesn't
mean you should".
A Dead-Simple HTML5 Slider
This is by the preferred method of implementing a slider. It "just works". Note that the UI for mobile screen reader users is very different between the two major operating systems:
- Under iOS/Voiceover: when the slider is focused, users must do a small swipe up and down to increase and decrease the slider values.
- Under Android/Talkback: when the slider is focused, users must use the device's volume keys to manipulate the slider.
Code Walkthrough of the Above Example
Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.
Although we give basic information cover how to style HTML5 Sliders, we do gloss over some minor cross-browser styling issues. More information on making them look super pretty can be found here:
- Style Input Range on-line generator tool can get you up and running quickly.
- A Sliding Nightmare: Understanding the Range Input by Ana Tudor is probably the most complete deep-dive I have seen on how to style HTML5 sliders (the old Microsoft Edge code is something we didn't implement here, since Microsoft Edge now relies on the same rendering engine Google Chrome uses). Recommended if you are trying to work out the cross-browser quirks between the two implementations.
An HTML5 Slider With Min and Max Values
Sometimes, the need comes up to have a slider with minimum and maximum values. Even though one single HTML5 range element can't do this, it is possible to combine two of them, with a little bit of CSS and surprisingly tiny amount of JS, to achieve this effect.
I cannot claim credit for this solution -- it's the work of the hugely talented Ana Tudor. Anyone interested in bleeding edge CSS and animation work should definitely check out Ana's Codepen and/or donating to help fund her research and mad scientist inclinations.
Code Walkthrough of the Above Example
Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.
ARIA Sliders
This NPM module is easily the one that took the longest to do. It is also the one that I would highly recommend to not use:
- It is quite a large module (based on code from Open Ajax Alliance's Slider Example with quite a few modifications to remove jQuery as a dependency.
-
I also refactored it to work with mobile. I couldn't use the same UI as the native
<input type="range">
, since using either iOS's vertical swiping and Android's hardware volume buttons to control the slider is impossible today. - HTML5 range inputs are so much easier to implement.
I honestly struggled as to whether it was a Good Idea to share this component to the outside world. In the end, I am posting this here as a great example of The First Rule of ARIA. I do think, however, that it shows an interesting use case for the mobile skip links as mobile only buttons, which could be used in something else in the future.
A note on all ARIA sliders on this page:
Note that all the ARIA sliders use the <template>
tag that the
JavaScript library will use to create the DOM elements:
Code Walkthrough of the Above Example
Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.
A Simple ARIA Slider
Code Walkthrough of the Above Example
Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.
An ARIA Slider With Min and Max Values
Code Walkthrough of the Above Example
Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.
Installation Instructions
You can load this JavaScript library into your application in serveral ways:
- as an ES6 module using Webpack.
- as a CommonJS module using
require()
and Webpack. - as a native ES6 module within the browser.
- as an old-school ES4/JavaScript library.
If you haven't done so already, choosing which you should use is obviously a major architectural decision. Here are a few articles that will help you decide:
- Jan Olaf Krems gives a great overview of the JavaScript File Format Differences
- Joe Honton discusses that With ES Modules and HTTP/2 You May Not Need Webpack Anymore
- Stack Overflow has a really good thread about Webpack vs ES6 modules as well.
Important Note On The CSS Classes Used In This Module:
This module requires specific CSS class names to be used in order it to work correctly.
These CSS classes begin with enable-slider__
. Please see the documentation above to see where these CSS classes are inserted.
Using NPM/Webpack to load ES6 Modules:
-
Install the
enable-a11y
NPM project. -
Edit your webpack.config.json file to resolve the
~
modifier by adding the following:module.exports = { ... resolve: { extensions: ['.js', '.jsx', '.scss', '.css', '*.html'], modules: [ path.resolve('./src/js'), path.resolve('./node_modules') ], alias: { '~enable-a11y': path.resolve(__dirname, 'node_modules/enable-a11y') }, ... }, ... }
-
You can use the module like this:
// import the JS module import enableSlider from '~enable-a11y/js/modules/enable-slider'; // import the CSS for the module import '~enable-a11y/css/enable-slider'; // How to initialize the enableSlider library enableSlider.init();
-
Alternatively, if you are using LESS you can include the styles in your project's CSS using:
@import '~enable-a11y/css/enable-slider';
.css
suffix)
Using NPM/Webpack to Load Modules Using CommonJS Syntax
-
Install the
enable-a11y
NPM project. -
You can import the module using require like this:
var enableSlider = require('enable-a11y/enable-slider').default; ... enableSlider.init();
- You will have to include the CSS as well in your project's CSS using:
@import '~enable-a11y/css/enable-slider';
Using ES6 modules natively.
This is the method that this page you are reading now loads the scripts.
- Grab the source by either using NPM, grabbing a ZIP file or cloning the enable source code from github.
-
If you want to load the module as a native ES6 module, copy
js/modules/enable-slider.js
,js/modules/interpolate.js
andcss/enable-slider.css
from the repo and put them in the appropriate directories in your project (all JS files must be in the same directory). -
Load the CSS in the head of you document:
<html> <head> ... <link rel="stylesheet" href="path-to/css/enable-slider.css" > ... </head> <body> ... </body> </html>
-
Load your scripts using the follwing code (NOTE: you must use
<script type="module">
):<script type="module"> import enableSlider from "path-to/enable-slider.js" enableSlider.init(); </script>
Using ES4
Just do the same as the ES6 method, except you should get the JavaScript files from thejs/modules/es4
directory instead of the js/modules/
:
<script src="path-to/es4/enable-slider.js"></script>