Hiding Content
Not all techniques for hiding web content are created equal. The choice of which to use can have dramatic consequences for accessibility.
Use of this guide can reduce mystery about why this happens and how to do better. The matrix here provides the full range of options on the Web Platform, with the helpful inclusion of testable examples. Thanks to Vincent Valentin for generously providing this as a resource to the web development community.
Access types
What makes this an interesting study is the large number of distinct and overlapping types of hiding. When content is hidden, access to it may be completely removed, but just as likely may only be partially restricted, with an overlapping set of access types still in effect. For example, a very common digital accessibility failure is to hide content visually but neglect to truly remove it from perception by assistive technologies.
A key understanding is that there are not two simple states, such as "visible and hidden." Depending on the technique, there are at least 13 composite states of access to partially hidden web content. Before considering them in combination, let's define each access type.
Definitions
- DOM access
- The element is in the document.
- Visual access
- The element is visible in the document.
- Layout access
- The element fills a space that will affect the rest of the layout.
- Semantic access
- The element has a meaning (title, list, emphasis…) that can be returned to user agents (screen readers, search engines…).
- Content access
- The information embedded in the element will be available.
- Keyboard access
- The element is reachable and usable by navigating on the keyboard (if it allows it natively).
- Pointer access
- The element is reachable and usable by navigating with a mouse or a tactile device (if it allows it natively).
- Styles access
- The element is always reachable via CSS and can be modified graphically.
- Subtree reverse access
- It is possible to reverse the removal on children.
Techniques
| Technique | DOM | Visual | Layout | Semantic | Content | Keyboard | Pointer | Styles | Subtree reverse |
|---|---|---|---|---|---|---|---|---|---|
JS .remove() |
no | no | no | no | no | no | no | no | no |
HTML <!-- -- > |
yes | no | no | no | no | no | no | no | no |
CSS display: none |
yes | no | no | no | no | no | no | no | no |
HTML hidden="hidden" |
yes | no | no | no | no | no | no | no | no |
HTML type="hidden" |
yes | no | no | no | no | no | no | no | no |
CSS visibility: hidden |
yes | no | yes | no | no | no | no | yes | yes |
HTML inert="inert" |
yes | yes | yes | no | no | no | no | yes | no |
CSS .mask, .sr-only… |
yes | no | no | yes | yes | yes | no | yes | no |
HTML aria-hidden="true" |
yes | yes | yes | no | no | yes | yes | yes | no |
HTML disabled="disabled" |
yes | yes | yes | yes | yes | no | no | yes | no |
CSS display: contents |
yes | yes | yes | yes | yes | no | yes | no | yes |
CSS opacity: 0 |
yes | no | yes | yes | yes | yes | yes | yes | no |
CSS position: absolute |
yes | yes | no | yes | yes | yes | yes | yes | no |
HTML tabindex="-1" |
yes | yes | yes | yes | yes | no | yes | yes | no |
HTML role="presentation" |
yes | yes | yes | no | yes | yes | yes | yes | yes |
HTML role="none" |
yes | yes | yes | no | yes | yes | yes | yes | yes |
CSS pointer-events: none |
yes | yes | yes | yes | yes | yes | no | yes | yes |
Default |
yes | yes | yes | yes | yes | yes | yes | yes | yes |