Checkbox hack alternatives

6 min. read

Caution! This article is 6 years old. It may be obsolete or show old techniques. It may also still be relevant, and you may find it useful! So it has been marked as deprecated, just in case.

The checkbox hack is when you use an <input> element of type "checkbox" to show or hide another element in the page by checking the state of its boolean attribute "checked".

Since show/hide sounds "boolean", it may seem like a good idea at first. But it's called a hack for a reason. It's bad semantics and accessibility is not the best. There was an article about it in the famous CSS tricks site, but even there it came with a disclaimer:

Disclaimer: Some of this stuff crosses the line of what you "should" do with CSS and introduces some bad semantics. It's still wicked fun to play with and cool that it's possible, but in general functional behavior should be controlled by JavaScript.

I totally agree that if you are going to make a switch you should use object-oriented JavaScript instead.

Main issues

  • semantics: form elements are to be used in forms, not in navigation lists, tabs or treelists.
  • it doesn't work on old iOs and on Android.
  • it relies on the :checked pseudo-class, which is not supported everywhere.
  • it may switch screen readers to form mode.
  • content of the shown element may be more difficult to read in form mode.
  • at the same time, display: none on the checkbox or on the toggable area will make it temporarily unreadable for screen readers which is confusing.

Other issues

  • The control will need to be well labelled so that the user knows exactly what the control does without relying on any text, icons or images around it. It would be good to look into "ARIA roles" to help with marking interactive elements in a more accessible way.

  • Also, the user may not know that a change has taken place once they have operated the control. In the checkbox hack, the only non-visual change is that the checkbox reports as "checked" when activated. That alone is not enough to signal the full extent of the control's purpose and status.

  • If you use this hack in several elements on the page, you could check any number of them and end up with all open, but you may want to only have one open at all times. This is very difficult to achieve with CSS only.

  • This hack is used a lot in dropdown menus. If you have a long list of elements, it is not scrolled so that it fits the screen.

  • Putting the label before the checkbox doesn't work. Since the ~ selector only has access to immediate siblings, nesting the checkbox inside a label also will not work, unless the target is inside the label as well.

  • And Lea also had something to add:

    @WebManWlkg The checkbox hack restricts the structure of the markup too much to make it practical for most use cases.

    — Lea Verou (@LeaVerou) 24 February 2016

Accessible hide/show solutions

I think JavaScript should not be abused and should be used only following a progressive enhancement approach. But for these kind of user interactions, if there is a lack of a native element, then often a solution involving both CSS and JavaScript is more accessible.

In particular, these two resources seem to be good sources of accessible widgets that you can use safely on your sites:

  • whatstock by Bryan Garaventa, who is blind himself. Comes with a lot of widgets.
  • a11y-togle by Edenspiekermann. If you don't find what you need in whatstock, try this one.

Other than this, the <details> and <summary> elements have a similar behaviour and are native to HTML.