Accessibility: It’s not as hard as you think
I’ve been fortunate enough to spend most of my career so far in an organisation where accessibility is part of the culture, so when I see inaccessible code, it’s as jarring to me as I’m sure code like this is to most developers who’ve learnt a bit about security:
mysql_query(“SELECT * FROM post WHERE id=$_GET[‘id’]”);
Accessibility is no harder than building in security, but it is a technique that has to be learnt.
We’re fortunate enough to have a team of in-house accessibility specialists who can periodically do in-depth reviews of our sites from an accessibility standpoint, but that feedback can be slow (especially in a world of automation and QA engineers embedded in a delivery team), so it’s best to sanity check your site first.
A quick checklist
My normal technique is to ensure non-mouse usability and then check for hard-of-sight users using a screen reader. Try using the tab key to move through your page.
- Can you get to every clickable element, or element that you need to be able to interact with, solely be the keyboard?
- Is it always visibly obvious where the focus is on the page?
- Does pressing enter on your keyboard do the same thing as clicking on it?
If you can do all of those things, you’ve got a good start. Next, try it with a screen reader. I use OSX with Chrome so this is pretty straight forward: Cmd+F5 will turn VoiceOver on (and off again), so have your page open and focussed and turn it on. Listen to your page being read out, does it all make sense? You can combine this with the keyboard test to check the non-visual UX of your site. Does activating a control result in some non-visual feedback?
Fixing the common mistakes
Normally when a site I’m working on fails the above, it’s down to a few simple things:
Alt text
Getting alt text right is tricky. Alt text is not a description of the image, it is a textual alternative for the purpose the image serves. Do you have a Facebook share icon? Then your alt text should be ‘Share on Facebook’, not ‘Facebook logo’. If your image is decorative, leave the alt text empty. Too often I’ve seen code like:
<div class="story">
<img src="/images/accessibility.jpg" alt="Accessibility checklist">
<h3>Accessibility checklist</h3>
</div>
All it does is annoy people who use screen readers by saying the content twice — this is a decorative image, it’s presence adds nothing to the meaning of the page.
The concept of alt text doesn’t just apply to images, although they do have a specific tag to see it. With the rise of icon fonts we’re now seeing graphical content which people aren’t giving textual alternatives to by default — so make sure that when you are using an icon font, you give a textual alternative too (there are tonnes of ways of doing this, using CSS clips or a negative text-indent are the most common ways).
Using non-semantic elements
Most issues I’ve seen when tackling accessibility bugs come from using the wrong type of element. <a href=“#”> is an anti pattern, if you find yourself doing this, you should use a button instead. Use lists, and use properly nested headings.
Sadly it seems that accessibility tools haven’t quite got caught up with HTML5, so you should still consider heading scope as global (i.e., article/section doesn’t reset the heading level). Also, a lot of non-sighted users use headings to navigate a document, so you should use actual HTML headings appropriately, and think of them more like anchor tags. e.g., the following code might appear fine, but it’ll cause people to miss the ‘breadcrumb’):
<article class="article">
<p class="article__breadcrumb">World News</p>
<h2 class="article__headline">Police Killing Sparks Unrest</h2>
</article>
Basically, headings are good — don’t be scared of using them.
No visual feedback on focus
I see this all the time, and it’s just so simple. Most browsers do a pretty decent job of this with outline rings, but sometimes we want to do better at that, so we give something a hover state in our CSS using the :hover pseudo-selector. Give it a :focus one too and you’ve basically got this one sorted (alternatively, if you’re doing something fancy with JS, as well as mouseover/mouseout, bind to focus/blur too).
Binding to a non-focusable element
A common mistake to make when you want to bind to, e.g., a list of links, is to add, for example, hover styling to the li, to make the focussed area as large as possible. However, by default an li can’t receive keyboard focus so you don’t get the same effect on keyboard navigation. You should make sure your :hover and :focus pseudo-selectors are based on things that are actually focussable, and style those elements appropriately.
Another mistake I’ve seen a few times is binding click events in JS to a div or a span — make it a button (if it has an action) an a (if it goes somewhere). If neither really make sense you could add a tabindex=“0" but if you can avoid it, that’s better.
No non-visual feedback on taking an action
This can happen if you want to override any anchor links, for example, to do pretty scrolling, or if you’re using the HTML5 history API. Or if you’ve got some AJAX forms. There are lots of ways to solve this one, e.g., if you have a button which toggles a tray, then you should move focus to the new tray that just opened so that a non-visual user can see what’s happened. There are also aria roles (e.g., aria-live) which can help here. When you think about the visual indications you give to a user (e.g., a modal to draw their eyes to something), make sure the state of focus reflects that too.
Losing focus whilst tabbing
If, whilst tabbing through the document you find your focus gets reset to the top of the document, that’ll be because the next item in the tab order will have become invisible as the focus moves (e.g., it may have been in a tray that is only visible when the previous item is hovered). To work around this, you should rework your interaction pattern to be less reliant on hovering or focus (e.g., introducing sticky toggling, etc)
This is far from a complete list, but if you’re doing all of these things, you’ll be doing well.