Enable
>

Accessible Checkboxes

This page shows different ways a checkbox can be marked up to see how screen readers will describe them to users.

A real styled HTML5 checkbox

This is the best solution to use, especially when building from scratch.
You can style an HTML5 checkbox using CSS easily. You don't need to make faux checkbox using <div> tags.

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.

☜ Scroll to read full source ☞

                    
                

A DIV with a role of checkbox

If you already are using a component similar to this in existing work that is not accessible, go to the developer walkthrough of this section to see we made our implementation accessible.

If you come across a <div> in existing code that is marked up like a checkbox, you can fix it this way. It is preferable to use the HTML5 version instead, if you can implement it quickly.

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.

☜ Scroll to read full source ☞

                    
                

HTML checkbox group

This is the best solution to use, especially when building from scratch.

If you have a group of checkboxes, this is the proper way to style them. Instead of fieldsets, you could use <role="group">, which is described in the ARIA form role example.

The following people will have my soul when I die:
You must choose at least one of the following.

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.

☜ Scroll to read full source ☞

                    
                

Indeterminate Checkboxes Using Native HTML

The parent/child hierarchy of this example has been done via an NPM module. (Module installation instructions)

We usually think of checkboxes being either checked or unchecked. There is a third possible state: indeterminate. The most common use-case for this, as outlined in the CSS Tricks article about Indeterminate Checkboxes, is for nested checkboxes. Consider you have a group of related attributes, like toppings in an ice-cream cone, that you can select with a group of checkboxes. It would be great to be able to have a "select all" checkbox that can choose all of them — because who doesn't want all the things on their ice-cream cone?!?! The problem is, what is this "select all" checkbox set to when some of the ingredients are checked but not all of them? While I have seen select all checkboxes not checked in this case, it can be argued that we give the indeterminate state for the checkbox.

Note that this indeterminate state can be set via JavaScript. There is no indeterminate HTML attribute. It is set like this:

☜ Scroll to read full source ☞

                    
                
How to use the indeterminate property in JavaScript

Note the last bit in the code above where we set the .checked property to false. This is done for progressive enhancement. While MDN reports that indeterminate is supported in all major browsers, we should still consider that not all browser/screen reader pairs (e.g. Firefox/NVDA, Firefox/Voiceover at the time of this writing) will announce the indeterminate state. For this reason, we should set the checked attribute to something that makes sense for screen reader users who use those browser/screen-reader pairs. Setting the checkbox to unchecked does make the most sense in this "Select All" scenario.

Now that we got the basics out of the way, let's see an example of this in action:

What toppings would you like on your ice-cream cone?
Checking this will automatically check the ingredient checkboxes below.

This example uses a library we developed to set up the hierarchical structure for the select all button to work. Below are the developer notes on how the library does it. If you are interested in using the library, please read the instructions on how to use the library in your own projects.

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.

☜ Scroll to read full source ☞

                    
                

Indeterminate Checkboxes Using ARIA

Just like two-state checkboxes, we can use ARIA to create faux-checkboxes. At the time of this writing, there is one advantage of doing so: Firefox using Voiceover and NVDA will report an indeterminate checkbox's state as mixed using ARIA.

☜ Scroll to read full source ☞

                    
                
How to use the indeterminate property in JavaScript
What toppings would you like on your ice-cream cone?
Checking this will automatically check the ingredient checkboxes below.

This example uses the same library we used in the native HTML5 example to set up the hierarchical structure for the select all button to work. As you compare the developer notes below to that of the HTML5 example, you will see the way to implement is similar. Please read the instructions on how to use the library in your own projects.

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.

☜ Scroll to read full source ☞

                    
                

How to Install the Hierarchical Checkbox library Into Your Projects

Installation Instructions

You can load this JavaScript library into your application in serveral ways:

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:

Using NPM/Webpack to load ES6 Modules:

  1. Install the enable-a11y NPM project.
  2. Edit your webpack.config.json file to resolve the ~ modifier by adding the following:
    ☜ Scroll to read full source ☞
    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') }, ... }, ... }
  3. You can use the module like this:
    ☜ Scroll to read full source ☞
    // import the JS module import hierarchicalCheckboxes from '~enable-a11y/js/modules/hierarchical-checkboxes'; // How to initialize the hierarchicalCheckboxes library hierarchicalCheckboxes.init();

Using NPM/Webpack to Load Modules Using CommonJS Syntax

  1. Install the enable-a11y NPM project.
  2. You can import the module using require like this:
    ☜ Scroll to read full source ☞
    var hierarchicalCheckboxes = require('enable-a11y/hierarchical-checkboxes').default; ... hierarchicalCheckboxes.init();

Using ES6 modules natively.

This is the method that this page you are reading now loads the scripts.

  1. Grab the source by either using NPM, grabbing a ZIP file or cloning the enable source code from github.
  2. If you want to load the module as a native ES6 module, copy js/modules/hierarchical-checkboxes.js from the repo and put them in the appropriate directories in your project (all JS files must be in the same directory).
  3. Load your scripts using the follwing code (NOTE: you must use <script type="module">):
    ☜ Scroll to read full source ☞
    <script type="module"> import hierarchicalCheckboxes from "path-to/hierarchical-checkboxes.js" hierarchicalCheckboxes.init(); </script>

Using ES4

Just do the same as the ES6 method, except you should get the JavaScript files from the js/modules/es4 directory instead of the js/modules/:
☜ Scroll to read full source ☞
<script src="path-to/es4/hierarchical-checkboxes.js"></script>