Skip to content

Styleguide: Accessibility

Brian Talbot edited this page Mar 12, 2015 · 57 revisions

General

This document is meant to be referenced alongside the following styleguides:


Recipes and Snippets


Other accessibility considerations


HTML5 Doctype

<!DOCTYPE html>

(BT: What does the doctype do for us? Should we list any brief reason why this is needed (I'm assuming for easier rendering and support of native elements.))


Landmarks and Roles

Landmarks and roles provide meaningful, semantic keys to specific sections of the page. This allows users of assistive technology to quickly jump to designated sections. These can also act as supplementary "skip navigation" mechanisms.

Header and Banner

The header element specifies a header for a document or section. It typically contains a heading (Level 1 to 6) for the document or section, but can also contain a table of contents, navigation, or a search field.

<header aria-label="Purpose of header">
    <!-- Stuff here -->
    ...
</header>

The ARIA role="banner" is used to indicate mostly site-oriented content rather than page-specific content.

<header role="banner" aria-label="Purpose of header">
    <!-- Page header -->
    ...
</header>
  • The header element should be used as a container for introductory content
  • You can have several header elements in one document
  • You may only use a single role="banner" and it must be used on a header element.
  • Always use an aria-label that describes (concisely) the purpose of the header. For example: "main" or "page".

Navigation

The nav element represents a section of a page that links to other pages or to parts within the page: a section with navigation links. The ARIA role="navigation" is used to indicate a collection of links to navigate the document or related documents.

<nav aria-label="Site">
    <!-- Screen readers would announce this as "Site navigation" -->
    <ul>
        <!-- List items with links -->
        ...
    </ul>
</nav>

Typical forms of navigation include site navigation, section navigation, page navigation, utility navigation, and footer navigation. The nav element usually wraps an unordered list, but doesn't have to.

  • You may use any number of nav elements.
  • Be sure to include an aria-label that describes the navigation as screen readers will include this information when the role is announced; don't include the word "navigation".

Main

The main element is used to indicate the content that relates directly to the central topic of the document.

<main>
    ...
</main>
  • There should only be one main element
  • Be sure to include aria-label="Content" so screen readers announce this as the "main content".

Search

The ARIA role="search" is used to define a region where search functionality is located.

<div role="search" aria-label="Course">
    ...
</div>
  • Be sure to include an aria-label that describes the scope of the search (i.e., site, course, notes, etc.)

Complementary

The ARIA role="complementary" is used to indicate content that is complementary to the main content, yet has meaning when separated from the main content.

<div role="complementary" aria-label="References">
    ...
</div>
  • Remember to add the aria-label that describes the scope of this complementary content, as it makes it easier for screen reader users to navigate directly to the region or browse a list of available regions on the page.

Footer, contentinfo

The ARIA role="contentinfo" indicates a region that contains information about the parent document. It often contains information like copyright and privacy statements and usually attached to the footer. This role is automatically implied when the footer element is used.

<footer aria-label="Article meta">
    ...
</footer>

<div role="contentinfo" aria-label="Website footer">
    <!-- Copyright, privacy, terms, etc. -->
    ...
</div>
  • Much like header, you may use multiple footer elements per page
  • Be sure to include a relevant and descriptive aria-label
  • You may use role="contentinfo" only once and it should be on the page footer

Native HTML5 elements

It's important to understand the native roles of elements and use them accordingly.

Form fields

Some of the more common input types that are useful to know are text, email, tel, and date. While these new types offer improved functionality for desktops, they really shine on mobile.

When adding form fields:

  • Always use a label that identifies the field (i.e., <label for="name">Name:</label><input id="name" />)
  • Establish a explicit connect between a label and an input by pointing the for to the id respectively
  • The name attribute isn't required, but it is helpful for normal form submissions that don't leverage JavaScript
  • Using aria-describedby and referencing an id will aid with help text that isn't contained within the label element. This comes in handy for help text or additional information about the data to be entered.
<input type="text">
  • Desktop: standard input field
  • Mobile: normal keyboard
<input type="email">
  • Desktop: standard input field
  • Mobile: keyboard tailored for easy email typing, including the @ symbol
<input type="tel">
  • Desktop: standard input field
  • Mobile: number pad keyboard suited for entering phone numbers
<input type="date">
  • Desktop: most newer browsers display a built-in datepicker
  • Mobile: usually a date spinner is presented for easy date picking

Buttons and Links

A good rule of thumb is: Buttons do something; links go somewhere.

Do this:

<button>I'll do something</button>

Not this (the role here isn't necessary):

<button role="button">I'll do something</button>

Or this:

<a href="#" role="button" class="button">Link that looks like a button</a>
  • button's are not required to appear within a form. Using the form element only aids with graceful degradation in instances where JavaScript isn't available.
  • It is recommended that you supply a type. The available types are:
    • submit: The button submits the form data to the server. This is the default if the attribute is not specified, or if the attribute is dynamically changed to an empty or invalid value.
    • reset: The button resets all the controls to their initial values.
    • button: The button has no default behavior. It can have client-side scripts associated with the element's events, which are triggered when the events occur.

Sections and Articles

The section element defines a section in a document. It should contain a heading. It should not be used as a stylistic wrapper as it has meaning.

<section>
    <h2>This is a list of articles</h2>
    <header>
        <nav role="navigation" aria-label="Article">
            ...
        </nav>
    </header>
    <article>
        <h3>Article title</h3>
    </article>
    ...
    <footer>
        ...
    </footer>
</section>

Taborder and Focus

Tab order is the order in which focus is moved throughout the document when navigating using the Tab key. Tab order follows the DOM and moves from the top of the DOM to the bottom. It is important ensure that the default tab order of your page presents elements in a logical order, even when manipulating the DOM with JavaScript.

If tab order must be set, there are two ways to do it:

#####taborder="0" allows an otherwise unfocusable element to be focused in the normal tab flow

#####taborder="-1" allows programmatic focus to be sent to an element through scripting

When opening a modal, send focus to it

HTML:

<div class="modal" tabindex="-1" aria-hidden="true">
    ...
</div>

Script:

var initiator = document.activeElement;
$('.modal').show().focus().attr('aria-hidden', 'false');

When closing a modal, return focus to the element that triggered it (initiator)

By sending focus back to the initiating control, we help maintain a natural, logical page flow.

HTML:

<button class="close">Close</button>

Script:

$('.modal').on('click', '.close', function() {
    $('.modal').hide().attr('aria-hidden', 'true');
    initiator.focus();
});

Note: When a modal or dialog box is opened, subsequent Tab presses should trap focus within the modal. Additionally, by pressing the ESC key should perform the same action as pressing the close button.


Using Icon Fonts

When using icon fonts, it's important to remember to:

  • use off-screen text if the icon is displayed by itself
  • hide the icon from audible output with aria-hidden="true"
  • never use an icon without equivalent text

Icons with visible labels

<a href="#"><i class="icon fa-question-mark" aria-hidden="true"></i> Get help</a>

Icons by themselves, without a visible label

<a href="#"><i class="icon fa-close" aria-hidden="true"></i> <span class="sr">Close</span></a>

Using aria-hidden

Make sure to include aria-hidden="true" with all icons. Otherwise screen readers may try to announce the icon which could confuse users.


Form Field Helper Text

Sometimes it's necessary to include helper text for a form field that's displayed below the field. Since screen readers read through the DOM linearly we need to ensure the helper text is announced.

Example:

<form>
    <label for="email-address">Email address:</label>
    <input type="email" name="email-address" id="email-address" aria-describedby="helper-email-address">
    <span id="helper-email-address">Must be a valid email address. Example: [email protected]</span>
</form>

Figures

For semantics, wrap your images in figures. You can have more than one img within a figure. Using a figcaption is optional but if used, should add clarity to the figure whether it's a single image or a collection of images.

A single image with a caption:

<figure>
    <img src="path/to/image.png" alt="Puppies playing in a field">
    <figcaption>Samwise Gamgee enjoys watching his puppies play in the green grass</figcaption>
</figure>

Multiple images, or charts, with a collective caption:

<figure>
    <img src="chart-01-apples.png" alt="46% apples" aria-describedby="chart-caption">
    <img src="chart-01-oranges.png" alt="54% oranges" aria-describedby="chart-caption">
    <figcaption id="chart-caption">Ratios and percentages comparing apples to oranges</figcaption>
</figure>

Note the use of aria-described here, programmatically linking the image to the caption


Hiding content

There are several mechanisms that can be used for hiding content. It's important that a technique be implemented that results in the desired outcome and accessibility.

Hiding content visually and aurally

These styles will hide text from all users. The text is removed from the visual flow of the page and is ignored by screen readers. Do not use this CSS if you want the content to be read by a screen reader. But DO use it for content you don't want read by screen readers or perceived visually.

display: none

Useful when:

  • Programmatically hiding or showing content that is in the DOM but not relevant to the current task
  • Loading a modal and its content
  • Loading tabbed content

Hiding content visually

A fairly modern technique of using CSS to hide or clip content that does not fit into a 1 pixel visible area will essentially hide the content visibly, but still allow it to be read by modern screen readers.

position: absolute;
clip: rect(1px, 1px, 1px, 1px);

Useful when:

  • Wanting to include additional/supporting/contextual information for screen readers, but hide it visually

Note: edX provides an .sr class that can be applied to any element or content that will automatically perform the above. We recommend using it.

Hiding content aurally

Sometimes we need to hide content from screen readers only, but have it shown to sighted users. This is primarily the case for icon fonts or other decorative stuff. Rather than using CSS to control this, we use HTML. You'd place the following in your markup:

aria-hidden="true"

An example of this would be:

<i class="icon-font icon-angle" aria-hidden="true"></i>

This would display the icon visually, but not announce it to screen readers. Since icon fonts often precede actual text, the text would still be announced and the action would still be clear. Hiding the icon only helps add clarity.

Useful when:

  • Wanting to hide certain decorative elements such as icons from assistive technology, but show them visually

Using images: DOM or CSS?

When it comes to using and including images in your document, where's the best place to put them? The easy answer is: If the image provides context or meaning, it should be in the DOM. A good example of this is the edX unit navigation which lets students navigate between sections within a course. The icons provide context as to which type of content to expect (video, assignment, problem, etc.) and should be included in the DOM (and therefore announced to screen readers).

If the images are purely decorative, they can be shown using CSS. If a decorative image is being used in the markup, be sure and use an empty alt attribute (alt="") so it's not announced.


Embrace the focus ring

The focus ring (the blue glow or dotted line that appears on buttons, links, or anything that has focus) is extremely important to people who rely on the keyboard to navigate. It indicates where focus is! Many designers disable or downplay the focus indicator, but this severely limits the ability to use a keyboard effectively and hurts the overall user experience.

We recommend leaving the styles alone and letting the browsers determine how they are displayed. If you feel strongly against the native browser styling of the outline and a focused state, you may re-style the focus (keeping in mind existing application focus style standards and options), but under no circumstances are you to remove it.

// Example: nope
:focus {
    outline: none;
}

// Example: Yep (but with consistent application outlines in mind)
:focus {
    outline: 2px solid yellow;
}

// Example: Yep (just use the browser default)
:focus {
}

Don't over-engineer

When building your site, take care not to overdo the engineering. Going overboard with ARIA can actually make your application less accessible. Understand the native roles of the elements you're using. Consider the following:

<button role="button">Button</button>

The role above isn't necessary because a button already has that role.

Similarly...

<a role="button">Link-tton</a>

Using role above changes the native role of the link. In this case, just use a button.

Clone this wiki locally