Developer workshop: Accessibility

Developer workshop: Accessibility

Government Digital Service (GDS)

Overview

Native keyboard behaviour

Interactive elements

HTML interactive elements are keyboard supported by default
w3.org/tr/html52/interactive-elements.html#interactive-elements

The a element

<a href="...">...</a>
State
focusable
Interaction
Enter

The button element

<button>...</button>
State
focusable
Interaction
Enter, Space

The select element

<select>...</select>
State
focusable
Interaction
Enter, up/down

Tab order

The tab order follows the DOM order of interactive elements

DOM order

<div>
<button>1</button>
<button>2</button>
<button>3</button>
</div>

DOM order demo

Flexbox order

<div style="display: flex;">
<button style="order: 3;">1</button>
<button style="order: 2;">2</button>
<button style="order: 1;">3</button>
</div>

Flex order demo

The tabindex attribute

The tabindex="0" attribute

<div>
<button>1</button>
<span tabindex="0" class="button">2</span>
<button>3</button>
</div>

tabindex="0" demo

The tabindex="-1" attribute

<div>
<button>1</button>
<button tabindex="-1">2</button>
<button>3</button>
</div>

tabindex="-1" demo

The .focus() method

<div id="dialog" tabindex="-1">...</div>

var dialog = getElementById("dialog");
dialog.focus();

The tabindex="N" attribute

<div>
<button tabindex="3">1</button>
<button tabindex="2">2</button>
<button tabindex="1">3</button>
</div>

tabindex="N" demo

Exercise 1: use a keyboard

Go to:
alphagov.github.io/a11y-dev-workshop/exercise1

Native semantics

Element roles

An element's role describes its purpose

The header element

<header>...</header>
Role
banner

The footer element

<footer>...</footer>
Role
contentinfo

The main element

<main>...</main>
Role
main

The nav element

<nav>...</nav>
Role
navigation

Screen reader demo

The ul element

<ul>...</ul>
Role
list

The li element

<ul>
<li>...</li>
<li>...</li>
</ul>
Role
listitem

Screen reader demo

The h1 element

<h1>...</h1>
Role
heading

Screen reader demo

The select element

<select>...</select>
Role
combobox

The input type="text" element

<input type="text">
Role
textbox

The input type="password" element

<input type="password">
Role
password

The input type="checkbox" element

<input type="checkbox">
Role
checkbox

Screen reader demo

States and properties

An element may be in a different state, or have different properties

The h1 element

<h1>...</h1>
Role
heading
Property
Level 1

The h2 element

<h2>...</h2>
Role
heading
Property
Level 2

Screen reader demo

The checked attribute

<input type="checkbox" checked>
Role
checkbox
State
checked

Screen reader demo

The disabled attribute

<button disabled>...</button>
Role
button
State
disabled

Screen reader demo

Exercise: use a screen reader

Jaws NVDA Voiceover Narrator

Go to:
alphagov.github.io/a11y-dev-workshop/exercise2

Custom semantics

Neutral elements

<div class="toolbar">
<span class="button">Bold</span><span class="button">Italic</span>...
</div>
Role
-
Name
-
State
-

Screen reader demo

Using ARIA

Attributes that polyfill missing role, name, and state information for screen readers

The role attribute

70+ roles, including:

The aria- attributes

45+ states and properties, including:

1st rule of ARIA

If you can use a native HTML element or attribute with the semantics and behaviour you require... then do so

2nd rule of ARIA

Do not change native semantics, unless you really have to

The wrong role attribute

<button role="heading" aria-level="1">Foo</button>
Role
heading
Name
Foo
Property
Level 1

Screen reader demo

3rd rule of ARIA

All interactive controls must be usable with a keyboard

Supplement existing interaction

<a href="#here" id="button" role="button">...</a>

var button = document.getElementById('button');
button.addEventListener('keydown', function(event) {
    if (event.keyCode == 13) {
        doSomething();
    }
});

Provide all interaction

<span id="button" role="button" tabindex="0">...</span>

var button = document.getElementById('button');
button.addEventListener('keydown', function(event) {
    if (event.keyCode == 13 || event.keyCode == 32) {
        doSomething();
    }
});

The application role

<body role="application">...</body>

Stops screen reader commands from working and hands navigation back to the browser

Other application mode roles

Other ARIA roles trigger applications mode, including:

4th rule of ARIA

Do not use role="presentation" or aria-hidden="true" on visible and focusable elements

The role="presentation" attribute

<button role="presentation">Foo</button>

Removes the element's semantics (but not its content)

Screen reader demo

The table element

<table role="presentation">...</table>

Useful workaround for layout tables

The role="none" attribute

<button role="none">Foo</button>

Introduced in ARIA 1.1 as a synonym for role="presentation"

The aria-hidden attribute

<button aria-hidden="true">Foo</button>

Removes the element from the accessibility tree

Screen reader demo

aria-hidden button

The hidden attribute

<nav hidden>...</nav>

Hides content from everyone

The display:none; property

<div id="reveal" style="display:none;">...</div>

Hides content from everyone, unless CSS is disabled

The 5th rule of ARIA

All interactive elements must have an accessible name

Accessible names

Identifies an instance of an element within an interface

Accessible descriptions

Provides additional descriptive information about an element

Accessible names and descriptions

The a element

<a href="https://gov.uk">Gov.UK</a>
Role
link
Name
Gov.UK

Screen reader demo

Speech recognition demo

The alt attribute

<img src="logo.svg" alt="Firefox logo">
Role
image
Name
Gov.UK

Screen reader demo

The label element

<input type="checkbox" id="uk">
<label for="uk">I live in the UK</label>
Role
checkbox
State
focusable unchecked
Name
I live in the UK

Screen reader demo

Speech recognition demo

The fieldset and legend elements

<fieldset>
<legend>Do you live in the UK?</legend>
<input type="checkbox" name="uk" id="yes">
<label for="yes">Yes</label>
<input type="radio" name="uk" id="no">
<label for="no">No</label>
</fieldset>

Screen reader demo

The aria-label attribute

<button aria-label="Search"><span class="icon"></span></button>
Role
button
Name
Search

Screen reader demo

The aria-labelledby attribute

<section aria-labelledby="services">
<h2 id="services">Services and information</h2>
...
</section>
Role
region
Name
Services and information

Screen reader demo

The aria-describedby attribute

<label for="tel">Your phone number</label>
<input type="text id="tel" aria-describedby="desc">
<p id="desc">Enter your phone number with no spaces</p>
Role
textbox
Name
Your phone number
Description
Enter your phone number with no spaces

Screen reader demo

Accessible name computation

Browser algorithm for calculating accessible names and descriptions
w3.org/tr/accname-aam-1.1/

Exercise 3: accessible names

For each example, identify the element's accessible name and/or description

Example 1

<button>Edit your answer</button>

Example 2

<button aria-label="Edit your address">Edit your answer</button>

Example 3

<label>Email address</label>
<input type="email" aria-describedby="desc">
<p id="desc">We will send confirmation to this email address</p>

Example 4

<img src="stock.jpg" alt="">

Example 5

<img src="browser-stats.svg" alt="Browser statistics chart"
aria-describedby="browser-stats-desc">
<div id="browser-stats-desc">
<p>A pie chart showing the percentage of visitors to Gov.UK using different browsers...</p>
</div>

Example 1: reminder

<button>Edit your answer</button>

Example 1: answer

Accessible name is "Edit your answer".

<button>Edit your answer</button>
Name
Edit your answer

Example 2: reminder

<button aria-label="Edit your address">Edit your answer</button>

Example 2: answer

Accessible name is "Edit your address".

<button aria-label="Edit your address">Edit your answer</button>
Name
Edit your address

Example 3: reminder

<label>Email address</label>
<input type="email" aria-describedby="desc">
<p id="desc">We will send confirmation to this email address</p>

Example 3: answer

No accessible name.

<label>Email address</label>
<input type="email" aria-describedby="desc">
<p id="desc">We will send confirmation to this email address</p>
Name
-
Description
We will send confirmation to this email address

Example 4: reminder

<img src="stock.jpg" alt="">

Example 4: answer

No accessible name.

<img src="stock.jpg" alt="">
Name
-

Example 5: reminder

<img src="browser-stats.svg" alt="Browser statistics chart"
aria-describedby="browser-stats-desc">
<div id="browser-stats-desc">
<p>A pie chart showing the percentage of visitors to Gov.UK using different browsers...</p>
</div>

Example 5: answer

Accessible name is "Browser statistics chart. Accessible description is "Pie chart showing...".

<img src="browser-stats.svg" alt="Browser statistics chart"
aria-describedby="browser-stats-desc">
<div id="browser-stats-desc">
<p>A pie chart showing the percentage of visitors to Gov.UK using different browsers...</p>
</div>
Name
Browser statistics chart
Description
A pie chart showing the percentage of visitors to Gov.UK using different browsers...

Accessibility mechanics

DOM tree

DOM tree of Gov.UK search

Accessibility tree

Acc tree of Gov.UK search

The input type="checkbox" element

<input type="checkbox" checked id="tc">
<label for="tc">Accept terms and conditions</label>
Role
checkbox
State
checked
Accessible name
"I live in the UK"

Screen reader demo

Accessibility APIs

Used by ATs to query accessibility information
smashingmagazine.com/2015/03/web-accessibility-with-accessibility-api/

Platform accessibility APIs

Accessibility API mappings (AAM)

Define how role, state, properties, and keyboard focus are handled in the browser

Browser accessibility support

An element may be supported in a browser, but not accessibility supported

Exercise 4: Inspect the accessibility tree

Go to:
alphagov.github.io/a11y-dev-workshop/exercise4

Accessibility acceptance criteria

Exercise 5: writing accessibility acceptance criteria

Go to:
alphagov.github.io/a11y-dev-workshop/exercise5

Component description

A single interactive component that lets a user show or hide content. Typically it is closed (collapsed) by default.

User story

"As an Assistive Technology (AT) user I want to know when additional content is available, how to access that content, and to know whether the content is currently shown or not"

Accessibility acceptance criteria: general

The disclosure component must:

Accessibility acceptance criteria: focus

Write accessibility acceptance criteria relating to focus

Accessibility acceptance criteria: focus

The disclosure control must:

Accessibility acceptance criteria: interaction

Write accessibility acceptance criteria relating to interaction

Accessibility acceptance criteria: interaction

The disclosure control must:

Accessibility acceptance criteria: appearance

Write accessibility acceptance criteria relating to appearance

Accessibility acceptance criteria: appearance

The disclosure control must:

Accessibility acceptance criteria: state

Write accessibility acceptance criteria relating to state

Accessibility acceptance criteria: state

The disclosure control must:

Exercise 6: testing

Go to:
alphagov.github.io/a11y-dev-workshop/exercise6

Example 1: issues

The disclosure control does not:

Example 2: issues

The disclosure control does not:

Asking questions

References

Things mentioned during the workshop:
github.com/alphagov/a11y-dev-workshop/bllob/gh-pages/references.md