Web Accessibility Cheat Sheet

My attempt to sum up a common accessibility practice that can be used for every application.

What is Accessibility (a11y)?

It’s the practice of making your websites usable by as many people as possible. Although it’s often considered as a focus to people with disabilities, the practice of making sites accessible also benefits other groups such as those using mobile devices, or those with slow network connections.

Practices and techniques

Semantic HTML

“lang” attribute

Use lang attribute. It provides screen readers the ability to use proper language for users. By default, it should be specified for the entire document:

1
2
<html lang="en">
...

Later if the document contains different languages, you may use this attribute to describe that language, e.g.

1
2
3
4
5
6
7
8
9
10
11
<ul>
<li>
<a href="/" lang="en">Hello</a>
</li>
<li>
<a href="/" lang="es">Hola</a>
</li>
<li>
<a href="/" lang="ru">Привет</a>
</li>
</ul>

Semantic elements

Prefer using semantic HTML elements instead of simple div, i.e. main, nav, section, article, aside. It helps screen readers better understand the logical structure of the document and focus on the proper content.

Btw, it’s applicable not only for screen readers but for search engine crawlers as well.

Screen readers

“alt” attribute for images whenever it’s possible

If you have the following markup:

1
<img src="leodavin.png" />

Very likely screen readers will pronounce it as “leodavin png, image” which might don’t have any sense for the listener.

But the following

1
<img src="leodavin.png" alt="Leonardo Da Vinci" />

will be pronounced as “Leonardo Da Vinci, image”.

It’s not always possible to use alt attribute for all images on the page since they might be uploaded by a user or used for decorative purposes. In these cases use an empty alt attribute:

1
<img src="shadowed_corner_top_right.png" alt="" />

labels are important

Prefer using of label element for input types in favor of div or span. Screen readers “read” the relationship between the text in label and input and it gives a context for a listener.

As an alternative, the one may use aria-labelledby attribute described below.

ARIA

ARIA stands for Accessible Rich Internet Application.

aria-labelledby
Establishes the relationship between objects and labels. This attribute should have an ID of elements that contains the text needed for labeling.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<--! Define the common text for whole section -->
<div id="myBillingId">Billing</div>

<div>
<--! Define the local text for the "Name" input -->
<div id="myBillingId myNameId">Name</div>

<--! Specify both IDs for the input -->
<input type="text"
aria-labelledby="myBillingId myNameId"/>
</div>

<div>
<--! Define the local text for the "Address" input -->
<div id="myAddressId">Address</div>
<--! Specify both IDs for the input -->
<input type="text" aria-labelledby="myBillingId myAddressId"/>
</div>

As a result, when input is focused, screen readers read it as “Billing Name, text” and “Billing Address, text”.

aria-describedby

Similar to aria-labelledby. The difference is that a label describes the essence of an object, while a description provides more information that the user might need.

1
2
3
4
5
6
7
8
<button aria-label="Close" 
aria-describedby="descriptionClose"
onclick="myDialog.close()">X</button>

<div id="descriptionClose">
Closing this window will discard any information entered
and return you back to the main page.
</div>

aria-live

Tells the screen reader that the area will be updating frequently.

Once the value of the progress bar will be updated - the user will be listening to the new value. There are 3 values:

  • off - default, turn off the updates.
  • polite - updates that are important for the user to receive, but not so rapid as to be annoying. The screen reader will speak changes whenever the user is idle.
  • assertive - should only be used for time-sensitive/critical notifications that absolutely require the user’s immediate attention. Generally, a change to an assertive live region will interrupt any announcement a screen reader is currently making. As such, it can be extremely annoying and disruptive and should only be used sparingly.

As an example, consider a progress bar component.

1
2
3
4
<div aria-label="Loading progress"
aria-live="polite">
10%
</div>

Whenever the status of the progress bar is updated - the user gets notified.

aria-relevant

Used with aria-live attribute to specify what kind of updates the one interested in: additions, removals, text, all.

The default setting is: additions text.

Keyboard shortcuts

Using of keyboard shortcuts helps not only people with disabilities but for power users as well. As an example, the Twitter has ? shortcut that opens the modal window with the list of all shortcuts:

  • j - next tweet
  • k - previos tweet
  • n - new tweet

Focus

  • Interactive content should be tabable (using Tab/Shift+Tab). Use tabindex="0" for non-interactive elements (custom components) to consider desired user path.
  • Don’t ignore :focus pseudo-selector. Some CSS libraries resets it in favor of design, but it break UX for people with disabilities. Focused elements should be noticeable.
  • Use skip links for providing users the short way to the content or navigation. Here’s an example of how to make it unobtrusive.

Colors

Avoid any flashes of content more than 3 times per second unless this content is sufficiently small, has low contrast, and don’t contain too much red color. It’s related to seizures and distraction.