Imagine you are blind, how do you understand a website? You would use a screen reader. All the text in a website is read out loud for you, from top to bottom. To navigate a site you can call a link list and a headings list.
The headings list you can use to navigate inside the page. Jump to a heading of interest and read from there. With the link list you can choose where to go next. There are more ways to navigate a site, but links and headings are most commonly used by screen reader users.
How can you decide where to go, when a lot of the links in a page are called “Read more”. Read more about what?
So, if you are a web developer, how can you help your blind visitor to understand your website? First of all: use headings that make sense. And second: use link texts that tell where they are linking to. And here the screen reader text comes in: it hides text from screen, but not from a screen reader.
For example links with the text “Read more”, “Continue reading” or a plain “>” or a font awesome icon. Looks neat and small and is incomprehensible for your blind visitor. But writing the whole post title in the read more link is long and ugly.
How to fix the “Read more” link?
Say you have the HTML:
<a href="url-here">Read more</a>
You can change this into:
<a href="url-here">Read more<span class="screen-reader-text"> about cute kittens</span></a>
For WordPress for example:
<a href="<?php the_permalink(); ?>">Read more<span class="screen-reader-text"> about <?php the_title();?></span></a>
And then you add the CSS in your stylesheet:
Note: this CSS is update on October 2017
/* Text meant only for screen readers. */
.screen-reader-text {
border: 0;
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
word-wrap: normal;
}
The element with the class screen-reader-text is made very small with clip, which needs the position absolute. Not visible for the eye, but read out load by a screen reader.
Don’t use display: none; or visibility: hidden. Screen readers don’t speak those, so that’s no use in this case.
Font awesome and other icons
How about your social media icons:
<i class="fa fa-twitter"></i>
It’s just an empty container and the <i> has a semantic meaning: text in an “alternate voice”.
Better use:
<span class="fa fa-twitter" aria-hidden="true"></span><span class="screen-reader-text">Twitter</span>
By the way: You can help changing this inaccessible way of implementing Font Awesome by joining the discussion in the Font Awesome GitHub.
Richard Senior did an excellent write up about WordPress, Font Awesome and Accessibility.
Labels in forms
A form input field needs a label. It’s just good practice and it tells a screen reader user what to fill out. A placeholder is no label, screen readers don’t read them well. But a label takes up space and maybe you don’t want that in your theme. So hide it with screen-reader-text.
For example in the WordPress search form:
<form role=”search” method=”get” class=”search-form” action=”url-here”>
<label for=”search-id” class=”screen-reader-text” >Search this website…</label>
<input name=”search” type=”text” value=”” placeholder=”Search this website…” id=”search-id”>
<input type=”submit” value=”Search”>
</form>
Hiding links
As a service to screen reader users and keyboard only users you can add skip links at the top of a page. That way a visitor can quickly jump to e.g. the content, without having to tab though the navigation.
They look something like this:
<ul class="skip-link">
<li><a href="#nav" class="screen-reader-text">Jump to main navigation</a></li>
<li><a href="#content" class="screen-reader-text">Jump to content</a></li>
<li><a href="#footer" class="screen-reader-text">Jump to footer</a></li>
</ul>
Some JavaScript is necessary to make skip links work properly.
If a visitor can see, it’s nice if the skip links are visible when they come in focus while tabbing though the links. So you can add the CSS to do that:
.screen-reader-text:focus {
clip: auto !important;
display: block;
height: auto;
width: auto;
z-index: 100000; /* Above WP toolbar. */
}
The screen reader text in more detail
Clip versus absolute positioning
.screen-reader-text {
position: absolute !important;
left: -999em;
}
This technique is pretty solid and works in all browsers however there are two main issues with this technique – its relatively easy to break, and it can cause a page “jump” if applied to focusable elements (like skip links and read more links), which can be very confusing to sighted keyboard users. [Reference: Jeff Burnz and Jonathan Snook]
Different ways of doing it
Gary Jones collected a few different ways of hiding text with clip. And there are more variations. Pick the one that suits your theme or adjust it to your needs.
What about:
clip: rect(1px, 1px, 1px, 1px);
versus
clip: rect(0, 0, 0, 0);
I couldn’t find a specific reason to use 0 or 1px, they both seem valid.
Back and forward compatibility
Clip is deprecated in CSS3, but supported by most browsers, it’s replaced by clip-path. Internet Explorer below version 8 doesn’t want a comma as separator and up to version 11 it doesn’t support clip-path yet, so you end up with:
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
clip-path: polygon(0px 0px, 0px 0px,0px 0px, 0px 0px);
The other way around: hide from a screen reader
The other way around is also possible. If you have an element that’s not relevant for screen reader users, you can hide it by adding aria-hidden=”true“.
This is used for example in the WordPress Admin for hiding a separator in the main menu.
<li class="wp-not-current-submenu wp-menu-separator" aria-hidden="true">
</li>
ARIA roles (Accessible Rich Internet Applications) are instructions for screen readers you can add to your HTML.
WordPress and the screen-reader-text
The name of the class is up to you, but “screen-reader-text” is the standard name for WordPress, and is used by WordPress core in the Admin and the front end and in the bundled themes like Twenty Fifteen. As from version 4.2 this class is WordPress generated CSS, so it’s important that you add it to your theme before updating to WordPress 4.2.
The screen-reader-text wil be used for the get_search_form, the comments_popup_link, the archives and categories dropdown widgets and will be used in more cases in future releases.
If you are a WordPress developer and want more controle over this, please support Gary Jones by commenting on his ticket add_theme_support( ‘screen-reader-text’ ).
Plugin
And if you can’t add the screen-reader-text class yourself to a WordPress theme: there’s a plugin for that.
Read more screen reader text: I knew you would check …
- Hiding content for accessibility by Jonathan Snook
- CSS in Action: Invisible Content Just for Screen Reader Users on WebAIM
- Hiding text for screen readers with WordPress Core by Joe Dolson
- Clip Your Hidden Content For Better Accessibility by Thierry Koblentz
- Understanding the CSS Clip Property by Hugo Giraudel
- Using CSS clip as an Accessible Method of Hiding Content in Drupal, by Jeff Burnz
- WordPress plugin “.screen-reader-text” theme support by Jaime Martinez
Photo Read More tattoo: Cory Doctorow.
Hi Rian,
Thank you very much for this article. Since reading it when you first published it, I’ve been using the screen-reader-text class as well as aria-hidden=”true” as you describe, and I find it works very well. I just discovered a couple little issues, though. I solved one of them easily, but I hope you can perhaps point me in the right direction for the other…
Let’s say I have a span with aria-hidden=”true” followed by a span with class=”screen-reader-text”, this works well on-screen to present visual content to sighted users and textual content to screen reader users, exclusively. But if the page is printed, both span elements are visible. This is easily resolved by adding display:none and/or visibility:hidden to the screen-reader-text class in Print CSS. However, the same issue occurs if text is copied and pasted. So my question is, would there be a way to prevent either aria-hidden=”true” or the screen-reader-text class from being copied/pasted?
Thank you very much for the guidance! I’ve learned a lot from reading your articles 🙂
Hi Julie, thank you for your kind words and for using the screen reader text class
I have no idea how to prevent the text form being copied. Sorry for that.
why not use aria-label or aria-labelledby
http://www.w3.org/TR/wai-aria/states_and_properties#aria-labelledby
Hi Donald,
Yes, a construction like:
is perfectly valid.
The drawback is that not all screen readers can read ARIA yet, so hiding with CSS is safer for now, but in the future: definitely.
Honestly, this is the best information I’ve found on using screen-reader-text.
Good stuff! Thank you.