This article is a translation from Cache-cache CSS by accessibility expert Gaël Poupard. All credits to him.
Or how to visually hide some text while keeping it accessible.
And even if I find this stupid—hiding text from some users but not others seems inherently wrong from an accessibility stand point to me—it’s a recurring need.
There are many ways of doing this, that I won’t detail here. For the past few years, I’ve been using this technique from Thierry Koblentz described on Yahoo!’s dev blog. It’s by far the most comprehensive, and—to my knowledge—the only way supporting RTL text orientation.
Unfortunately it’s not without issue anymore.
Deprecated property
The “magic trick” of this solution relies on the clip
property. It’s simple to understand and very efficient. Only downside: clip
has been deprecated by the CSS Masking Level 1 module.
No worries. This technique being quite old now, there is no surprise it’s getting obsolete. The new specification recommends using clip-path
to replace clip
. Which is not ideal, because clip-path
support is still so-so. Thus we have to keep clip
and add clip-path
as progressive enhancement.
That being said, the syntax is different. After a bit of research, Yvain Liechti suggested this short version to get the expected result:
clip-path: inset(50%);
Problem solved.
Shrinked text
J. Renée Beach warned about the width: 1px
declaration having side effects on text rendering and therefore on its vocalisation by screen readers.
The suggested solution is both simple and logical: preventing the text from wrapping so that spaces between words are preserved.
Only one declaration does that:
white-space: nowrap;
Problem solved again.
Wrapping things up
Here is the final version I came up with:
.sr-only {
border: 0 !important;
clip: rect(1px, 1px, 1px, 1px) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
white-space: nowrap !important;
}
Warning
This technique should only be used to mask text. In other words, there shouldn’t be any focusable element inside the hidden element. This could lead to annoying behaviours, like scrolling to an invisible element.
That being said, you may want to hide a focusable element itself; a common candidate are skip links (a WCAG 2.0 technique). Most of the time we hide them until they get the focus.
Bootstrap and HTML5 Boilerplate have a pretty good solution for this: another class meant to reset these properties.
Here is the adapted version:
.sr-only-focusable:focus,
.sr-only-focusable:active {
clip: auto !important;
-webkit-clip-path: none !important;
clip-path: none !important;
height: auto !important;
overflow: visible !important;
width: auto !important;
white-space: normal !important;
}
Go for it
You can find it on CodePen or in this Gist. What do you think?
Screen readers and touch devices (edit: 19/10/2016)
Seeking some testers to make sure I didn’t cause any regression, Johan Ramon met a strange bug with VoiceOver. Digging further with Sylvain Pigeard, we found out that position: static
is buggy on iOS 10 + VO when .sr-only-focusable
is focused.
As we thought we discovered a real bug, I headed up to Bootstrap in order to open an issue. But it came out that an issue was already opened, involving TalkBack too. I shared our result to contribute, then Patrick H. Lauke did an awesome (and still in progress) work to determinate and describe precisely the problem. As a result, he filled many bugs:
- Narrator, included in Windows 10 and Windows Phone;
- Chromium, impacting TalkBack on Android;
- Firefox — this one was already opened, but also by Patrick Lauke recently;
- and finally, two bugs for Webkit, impacting VoiceOver.
So. In fact, skip links don’t work with screen readers on touch devices at the time of writing. Nice.
SEO
Steve Faulkner from the Paciello Group asked to the Google Webmaster Central Help Forum directly if extra context for vision impaired users has a negative effect on search ranking?.
Short answer: nope. However visually hidden content are considered secondary, in order to prevent abuses. And that’s great.