Accessibility - acnorrisuk/coding-style-guide GitHub Wiki

Boilerplate

Always declare the correct doctype. Omitting it can result in unexpected and broken behaviour.

<!doctype html>

Make sure a language attribute is added to the html element. This allow screen readers to read out text with the correct voice profile and can help with spelling highlighting for users filling out forms.

<html lang="en-GB">

The viewport meta tag should not restrict scaling as this can cause issues on small screens where users may wish to zoom in to view content (Note: most browsers now ignore the restrictions, but it's safer not to add it just in case).

<!-- bad -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0 user-scalable=no">

<!-- good -->
<meta name="viewport" content="width=device-width, initial-scale=1">

Style

Typographic should be chosen and set with readability in mind. Increasing the default font-size, line height and limiting the line length of text can help make text more legible.

/* an example of readable typography */
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 110%;
line-height: 1.5;
max-width: 60em;

In general, text should be set in ems or rems to allow for text resizing in various browsers.

/* Can cause some issues when zooming in older browsers */
h1 {
  font-size: 50px;
}

/* A more fluid approach */
h1 {
  font-size: 3.125em;
}

Where possible, fluid values should be used (em, rem, or %) on elements to prevent designs from 'breaking' when users zoom into content.

The contrast ratio of text should not exceed 4.5:1 for normal text and 3:1 for large text. You can test this by using a tool such as color contrast checker

Ensure that you aren't just using color to convey meaning (e.g. links, buttons, form validation) as this may not be seen by all users.

/* Can cause issues for people with colour vision deficiency */
a {
  text-decoration: none;
  color: blue;
}

Semantics

Wherever possible, semantic HTML elements should be used as they help assistive technology understand what type of information they may contain.

<!-- div and span have no semantic meaning -->
<div>
  <img src="someimage.jpg" alt="some image">
  <p>Image caption <span>by author</span></p>
</div>

<!-- more semantic -->
<figure>
  <img src="someimage.jpg" alt="some image">
  <figcaption>Image caption <em>by author</em></figcaption>
</figure>

In the case where there are no relevant semantic elements available (such as with tab panels), ARIA should be used to provide cues to assistive technology. (See W3C Spec)

Landmark roles should be used to help users navigate your site via keyboard shortcuts.

Note Many of the landmark roles are implied with HTML5 but still should be added as screen reader support is still sketchy.

<!-- examples of landmark roles -->
<header role="banner">
<nav role="navigation">
<main role="main"> <!-- Only one of these should be used on a page -->
<article role="article">
<aside role="complementary">
<footer role="contentinfo">
<form role="search">

A clear heading structure should be used to help those using keyboard shortcuts. Only one <h1> should appear on the page followed by <h2> - <h6> where necessary. Heading levels should not be skipped as this can be disorientating for users.

<!-- poor heading structure -->
<h1>Example Heading</h1>
  <h3>Some Subheading</h3>

<!-- better heading structure -->
<h1>Example Heading</h1>
  <h2>Some Subheading</h2>

Heading elements should not be used for subheadings unless they need their own subsection

<!-- unnecessary heading -->
<h1>Main heading</h1>
<h2>tagline</h2>

<!-- better -->
<h1>Main heading<h1>
<p>tagline</p>

Naming

Ensure any interactive elements (such as links/buttons or other controls) have a name associated with them.

<!-- This item is named by its contents -->
<a href="#">Link to somewhere</a>

<!-- This item is named by aria-label -->
<button aria-label="close">X</button>

<!-- This item is named by aria-labelledby -->
<h2 id="article">Article Heading</h2>
<a aria-labelledby="article">read more</a>

<!-- This item is named by its title -->
<svg...>
  <title>Company Logo</title>
</svg>

It may also be necessary to add in content just for screen readers to help describe content. To do this you can apply a screen reader only class to your markup.

/* Show to assistive technology */
.screen-reader {
  position: absolute;
  clip: rect(1px 1px 1px 1px); /* for Internet Explorer */
  clip: rect(1px, 1px, 1px, 1px);
  padding: 0;
  border: 0;
  height: 1px;
  width: 1px;
  overflow: hidden;
}
<!-- Using a screen reader class to add more information -->
<a href="some-url.com">Read more<span class="screen-reader-text"> about cute kittens</span></a>

Media

All <img> elements should have an alt attribute to describe the content of the image. Images which are purely decorative should use an empty alt attribute. Visit WebAIM.org to see guidance for providing quality alt text.

<!-- content image -->
<img src="cat.jpg" alt="A small cat taking a drink from a bowl">

<!-- decorative image -->
<img src="background.jpg" alt="">

Text alternatives should be provided for audio and video elements.

Functionality

Using native HTML elements is preferred over repurposing other elements (e.g. using <button> instead of <div>) as accessibility is often baked-in. The <a> element should be reserved when navigating to a link (i.e. anything which starts with http:// or https://). See Links vs. buttons in modern web applications.

<!-- no native accessibility -->
<div id="toggle">Menu</div>

<!-- built in accessibility -->
<button id="toggle">Menu</button>

Using the :focus pseudoclass when setting :hover styles can help improve the user experience (remember this can only be set on focusable elements such as links and buttons).

.btn:hover, .btn:focus {
  background-color: #333;
  color: #fff;
}

Focus outlines should not be removed with CSS, these are important for those using keyboard navigation. However, they can be styled to suit your application.

a:focus {
  background-color: #ffbf47;
  outline: 3px solid #ffbf47;
}

Forms

All form inputs should have labels associated with them. This can be associated using the for attribute, or alternative, the label can wrap around the element. This allows users to click the label to use the form controls - this is especially helpful for checkboxes and radio buttons.

<!-- Using for to label an input field -->
<label for="lastname">Last name:</label> 
<input type="text" name="lastname" id="lastname">

<!-- Using a wrapping label -->
<label>Last name:
  <input type="text" name="lastname">
</label> 

For form inputs with many options (e.g. multiple radio buttons), you can wrap the group in a fieldset and add a legend. This can help prevent users from getting lost when using the controls.

<!-- example of fieldset from http://webaim.org/techniques/forms/controls -->
<fieldset>
  <legend>Choose a shipping method:</legend>
  <input id="overnight" type="radio" name="shipping" value="overnight">
  <label for="overnight">Overnight</label><br>
  <input id="twoday" type="radio" name="shipping" value="twoday">
  <label for="twoday">Two day</label><br>
  <input id="ground" type="radio" name="shipping" value="ground">
  <label for="ground">Ground</label>
</fieldset>

Testing

Mac OS has a built in screenreader (VoiceOver) and Chrome has an upcoming accessibility tool currently hidden behind a flag (see guide)

Some common accessibility testing tools:

WAVE Site Test

aXe Chrome Plugin

Tenon Site Test

Some accessibility checklists:

Webaim Checklist

18F Checklist

Some accessibility guides:

WCAG Guidelines

A11y Style Guide

A11y Project

⚠️ **GitHub.com Fallback** ⚠️