Check-All / Expand-All Controls

Controls that can operate other controls in bulk are not new. One common example is a single checkbox that allows you to check or uncheck a group of checkboxes. Another example is a single button that lets you expand or collapse a set of disclosure widgets. When the user operates one from the set, the bulk control then reflects that.

For example, you may choose “All toppings” for your ice cream sundae, which checks every checkbox for every topping. Then you uncheck “Butterscotch” because you want to exclude that terrible sauce. The “All toppings” checkbox should visually and programmatically change to reflect that not all toppings are checked.

You can visit the demo directly. Bear in mind it is not production-ready code.

WCAG

WCAG Success Criterion 4.1.2 Name, Role, Value requires that the state of the bulk operation control is conveyed programmatically.

That “check all” or “expand all” control has to support situations where not everything it controls is currently in the same state as the others. This means a simple on/off won’t do; you need a control that supports three states — a tristate control.

HTML

Only one HTML control supports tristate, and that is the checkbox. While the WHATWG HTML specification says it is not a tristate control, authors can use script to set a checkbox to “indeterminate”, which is exposed to users through platform accessibility APIs as “mixed”.

Authors could use aria-checked="mixed", but don’t do this unless you are making a custom ARIA checkbox or menuitemcheckbox (ugh). For HTML checkboxes the HTML programmatic state overrides the ARIA programmatic state, so it’s best not to use it. See § 3.5.18 and § 3.5.19 of HTML Accessibility API Mappings 1.0 for more detail than I am interested in giving in this sub-500 word post.

ARIA

Only one non-HTML ARIA control supports tristate, specifically via aria-pressed through the mixed value. Be aware that the aria-pressed attribute is only allowed on a <button> (or button role, but ugh).

A switch control is not an option since it allows only two states — the ARIA switch role disallows a mixed state. The proposal to make a native HTML switch control also disallows a mixed state. You can read more in my post Switch Role Support.

Recap

To recap, here are your options:

This advice is not absolute, of course.

4 Comments

Reply

We’ve struggled a bit with similar expand/collapse controls in the component library I’ve been involved with. Originally we had an expand/collapse HTML button where the button text is always “Expand all” if there is at least one collapsed section, and “Close all” if all sections are open. The button had an aria-expanded=”true/false” attribute which was removed on my recommendation, since it wasn’t really appropriate in the first place and also didn’t reflect the mixed state accurately. Also changing both text and state can be confusing, even though I have it done even in some W3C examples.

Your suggestion of using a button with aria-pressed is interesting, but my issue with it is that on its own it does not communicate what will happen when the user presses the button in the “mixed” state. Do the sections collapse or expand? Because of this we now have only a button where we change the text and nothing else: this seems to most accurately convey what the button does in every situation. I know some screen readers will not immediately communicate the change in the accessible name without refocusing, but this seems less of a nuisance than having potentially confusing or conflicting state and accessible name. I would appreciate your thoughts on this!

Daniel Koskinen; . Permalink
In response to Daniel Koskinen. Reply

[…] my issue with it is that on its own it does not communicate what will happen when the user presses the button in the “mixed” state. Do the sections collapse or expand?

Broadly speaking, my experience is that users are accustomed to checking the first item past the “do all” control since that first item acts as a proxy for the entire set. That being said, you can choose to always do one or the other and then include that in instructions.

I know some screen readers will not immediately communicate the change in the accessible name without refocusing, but this seems less of a nuisance than having potentially confusing or conflicting state and accessible name.

In the end, those are effectively the same thing — requiring the user to explore subsequent related controls. An accessible name that lies about the state is little different for users than a state and name that is ambiguous. Arguably, the first sows distrust while the second is at least honest about its ambiguity. Unless you address it as I noted just above, of course.

In response to Adrian Roselli. Reply

Thank you for the reply and insight! As I see it, changing the visible label (as we are doing now) allows for a more explicit indication of what will happen, i.e. “Expand all” or “Collapse all”. What I gather from this, is that for screen reader use, the lack of a state on the button is not an issue because the label already says what will happen, and users can verify this by moving to the first item in the set. Aria-pressed would only work well with a constant label.

Daniel Koskinen; . Permalink
In response to Daniel Koskinen. Reply

As I see it, changing the visible label (as we are doing now) allows for a more explicit indication of what will happen, i.e. “Expand all” or “Collapse all”.

Provided the user knows the language of the page and does not auto-translate it into something that may be… weird. Though if (when) the visible label (which I hope is also the accName) falls out of sync with the current state you will have problem of lying to users. Which I note in my previous reply.

What I gather from this, is that for screen reader use, the lack of a state on the button is not an issue because the label already says what will happen, and users can verify this by moving to the first item in the set.

We disagree there. The lack of state means the author has to have to have conveyed the meaning and intent properly (in addition to intended state). My experience is that is not always (nor often enough) the case.

Aria-pressed would only work well with a constant label.

You have that inverted. aria-pressed works well unless you have an inaccurate label.

Either way, all that matters is whatever solution you use works for your users. So speculate as much as necessary to inform a prototype, then build it, then get it in front of your users, then decide based on those outcomes.

Leave a Comment or Response

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>