There are times when you need to pick and choose when you're going to hide things visually, remove it from the DOM, hide things from screen readers, or show things (like text alternatives, or keyboard-focused content) only to those using assistive technology. Let's take a look at the different techniques that are available to us.
Visibility Cheat Sheet
Here we can quickly scan to see what properties affect screen readers, prevent elements from being accessible by the tab key, or remove them from the visual flow (i.e. taking up layout space, whether or not they are painted).
| Hidden from screenreaders | Removed from the tab flow | Removed from the visual flow | |
|---|---|---|---|
aria-hidden="true" |
☑ | ☒ | ☒ |
Native HTML hidden attribute |
☑ | ☑ | ☑ |
CSS display: none; |
☑ | ☑ | ☑ |
CSS visibility: hidden; |
☑ | ☑ | ☒ |
CSS font-size:0; (for inline elements) |
☒ | ☒ | ☑ |
| Techniques* for visually hiding block-level elements | ☒ | ☒ | ☑ |
| * See different techniques below. | |||
Wondering exactly which assistive technologies support which properties? While there's unfortunately no service as robust as caniuse.com Opens in a new window for screenreaders, Steve Faulkner Opens in a new window is doing really incredible work over at html5accessibility.com Opens in a new window in documenting exactly that. Check out his tests for visibility techniques Opens in a new window.
Techniques from Popular Front-end Libraries
Let's take a look at the different approaches of popular front-end libraries towards
- showing content only to screen readers, and
- showing content only when focused via the keyboard (a.k.a 'tabbing').
Note that I've taken some small liberties with the property order, strictly for the purposes of readability in comparing the different libraries.
WebAIM
Before we look at the libraries' approaches, for context let's look at WebAIM's recommended technique Opens in a new window for showing content only to screen readers or keyboard-navigators.
.webaim {
/**
Declaring fixed dimensions avoids certain
opinionated browsers removing your content
from the DOM.
*/
height: 1px;
width: 1px;
overflow: hidden;
/**
Here we position the element well offscreen
and remove it from the document flow.
*/
left: -10000px;
position: absolute;
top: auto;
&:focus {
/**
On the focus event, we return the element
to the document flow and let the content
set the dimensions. Note that a static position
means that the 'top' property has no effect.
*/
height: auto;
position: static;
width: auto;
}
}
Foundation
I'm a big fan of Foundation Opens in a new window. Sure, it's light-weight, fully featured and easy to use. But it also puts accessibility first in every component - not as an afterthought.
.foundation.show-for-sr,
.foundation.show-on-focus {
border: 0;
clip: rect(0, 0, 0, 0);
// Unique to Foundation
clip-path: inset(50%);
height: 1px;
overflow: hidden;
padding: 0;
// !important declaration unique to Foundation
position: absolute !important;
white-space: nowrap;
width: 1px;
}
.foundation.show-on-focus:active,
.foundation.show-on-focus:focus {
clip: auto;
// Unique to Foundation
clip-path: none;
height: auto;
overflow: visible;
// !important declaration unique to Foundation
position: static !important;
white-space: normal;
width: auto;
}
Bootstrap
Bootstrap Opens in a new window continues to be a juggernaut in front-end component libraries. Accessibility has improved starting with v4, but it continues to play catch-up with Foundation.
.bootstrap.sr-only {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
overflow: hidden;
padding: 0;
position: absolute;
white-space: nowrap;
width: 1px;
}
.bootstrap.sr-only-focusable:active,
.bootstrap.sr-only-focusable:focus {
clip: auto;
height: auto;
overflow: visible;
position: static;
white-space: normal;
width: auto;
}
HTML5 Boilerplate
HTML5 Boilerplate has a little 'gotcha' here, where you need both .visuallyhidden and .focusable classes on an element in order to toggle with keyboard focus.
.html5-boilerplate.visuallyhidden {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
// Unique to Boilerplate
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
white-space: nowrap;
width: 1px;
}
.html5-boilerplate.visuallyhidden.focusable:active,
.html5-boilerplate.visuallyhidden.focusable:focus {
clip: auto;
height: auto;
margin: 0;
overflow: visible;
position: static;
// Unique to Boilerplate
white-space: inherit;
width: auto;
}
Bulma
Aside from a few haphazard aria attributes, Bulma has almost no accounting for accessibility. Be prepared to do all your accessibility from scratch if you use Bulma.
Techniques in action
Here's a Pen that shows the behaviour of all the different properties and techniques we've discussed here!
See the Pen Hiding Techniques by Simon Borer (@simonborer) on CodePen.
