Quiz

What are the different ways to visually hide content (and make it available only for screen readers)?

Topics
AccessibilityCSS
Edit on GitHub

These techniques are related to accessibility (a11y).

Small/zero size

width: 1px; height: 1px and a combination of using CSS clip to make the element take up (barely any) space on the screen at all.

Using width: 0; height; 0 is not recommended because search engines might penalize this thinking it has a malicious intention, like keyword stuffing.

Absolute positioning

position: absolute; left: -99999px will position an element way outside of the screen. However, as per WebAIM's article:

Navigable elements, such as links and form controls, should not be hidden off-screen. They would still be navigable by sighted keyboard users, but would not be visible to them, unless they are styled to become visible when they receive keyboard focus.

Use this only when your contents contain only text.

Text indentation

text-indent: -9999px. This only works on text within the block elements. Similar to the absolute positioning technique above, focusable elements given this style will still be focusable, causing confusion for sighted users who use keyboard navigation.

Incorrect ways

The following ways are incorrect because they hide content from the user AND screen readers, which is incorrect if the purpose is to expose to screen readers only.

  • display: none
  • visibility: hidden
  • hidden attribute

Techniques in the wild

Ideally, it is recommended to combine the above approaches to make sure it works properly in all browsers.

Instead of implementing your own way to remove an element from the rendering tree and the a11y tree, you are recommended to use one of the following approaches from mature CSS frameworks, which have been battle-tested on many websites.

Tailwind CSS

.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}

Bootstrap CSS

.visually-hidden,
.visually-hidden-focusable:not(:focus):not(:focus-within) {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip: rect(0, 0, 0, 0) !important;
white-space: nowrap !important;
border: 0 !important;
}

References

Edit on GitHub