Government Digital Service (GDS)
HTML interactive elements are keyboard supported by default
w3.org/tr/html52/interactive-elements.html#interactive-elements
a
element<a href="...">...</a>
button
element<button>...</button>
select
element<select>...</select>
The tab order follows the DOM order of interactive elements
<div>
<button>1</button>
<button>2</button>
<button>3</button>
</div>
<div style="display: flex;">
<button style="order: 3;">1</button>
<button style="order: 2;">2</button>
<button style="order: 1;">3</button>
</div>
tabindex
attributetabindex="0"
attribute<div>
<button>1</button>
<span tabindex="0" class="button">2</span>
<button>3</button>
</div>
tabindex="0"
demotabindex="-1"
attribute<div>
<button>1</button>
<button tabindex="-1">2</button>
<button>3</button>
</div>
tabindex="-1"
demo.focus()
method<div id="dialog" tabindex="-1">...</div>
var dialog = getElementById("dialog");
dialog.focus();
tabindex="N"
attribute<div>
<button tabindex="3">1</button>
<button tabindex="2">2</button>
<button tabindex="1">3</button>
</div>
tabindex="N"
demoGo to:
alphagov.github.io/a11y-dev-workshop/exercise1
An element's role describes its purpose
header
element<header>...</header>
footer
element<footer>...</footer>
main
element<main>...</main>
nav
element<nav>...</nav>
ul
element<ul>...</ul>
li
element<ul>
<li>...</li>
<li>...</li>
</ul>
h1
element<h1>...</h1>
select
element<select>...</select>
input type="text"
element<input type="text">
input type="password"
element<input type="password">
input type="checkbox"
element<input type="checkbox">
An element may be in a different state, or have different properties
h1
element<h1>...</h1>
h2
element<h2>...</h2>
checked
attribute<input type="checkbox" checked>
disabled
attribute<button disabled>...</button>
Go to:
alphagov.github.io/a11y-dev-workshop/exercise2
<div class="toolbar">
<span class="button">Bold</span><span class="button">Italic</span>...
</div>
Attributes that polyfill missing role, name, and state information for screen readers
role
attribute70+ roles, including:
aria-
attributes45+ states and properties, including:
aria-invalid
, aria-required
aria-pressed
, aria-expanded
aria-controls
, aria-owns
If you can use a native HTML element or attribute with the semantics and behaviour you require... then do so
Do not change native semantics, unless you really have to
role
attribute<button role="heading" aria-level="1">Foo</button>
All interactive controls must be usable with a keyboard
<a href="#here" id="button" role="button">...</a>
var button = document.getElementById('button');
button.addEventListener('keydown', function(event) {
if (event.keyCode == 13) {
doSomething();
}
});
<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();
}
});
application
role<body role="application">...</body>
Stops screen reader commands from working and hands navigation back to the browser
Other ARIA roles trigger applications mode, including:
Do not use role="presentation"
or aria-hidden="true"
on visible and focusable elements
role="presentation"
attribute<button role="presentation">Foo</button>
Removes the element's semantics (but not its content)
table
element<table role="presentation">...</table>
Useful workaround for layout tables
role="none"
attribute<button role="none">Foo</button>
Introduced in ARIA 1.1 as a synonym for role="presentation"
aria-hidden
attribute<button aria-hidden="true">Foo</button>
Removes the element from the accessibility tree
hidden
attribute<nav hidden>...</nav>
Hides content from everyone
display:none;
property<div id="reveal" style="display:none;">...</div>
Hides content from everyone, unless CSS is disabled
All interactive elements must have an accessible name
Identifies an instance of an element within an interface
Provides additional descriptive information about an element
a
element<a href="https://gov.uk">Gov.UK</a>
alt
attribute<img src="logo.svg" alt="Firefox logo">
label
element<input type="checkbox" id="uk">
<label for="uk">I live in the UK</label>
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>
aria-label
attribute<button aria-label="Search"><span class="icon"></span></button>
aria-labelledby
attribute<section aria-labelledby="services">
<h2 id="services">Services and information</h2>
...
</section>
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>
Browser algorithm for calculating accessible names and descriptions
w3.org/tr/accname-aam-1.1/
For each example, identify the element's accessible name and/or description
<button>Edit your answer</button>
<button aria-label="Edit your address">Edit your answer</button>
<label>Email address</label>
<input type="email" aria-describedby="desc">
<p id="desc">We will send confirmation to this email address</p>
<img src="stock.jpg" alt="">
<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>
<button>Edit your answer</button>
Accessible name is "Edit your answer".
<button>Edit your answer</button>
<button aria-label="Edit your address">Edit your answer</button>
Accessible name is "Edit your address".
<button aria-label="Edit your address">Edit your answer</button>
<label>Email address</label>
<input type="email" aria-describedby="desc">
<p id="desc">We will send confirmation to this email address</p>
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>
<img src="stock.jpg" alt="">
No accessible name.
<img src="stock.jpg" alt="">
<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>
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>
input type="checkbox"
element<input type="checkbox" checked id="tc">
<label for="tc">Accept terms and conditions</label>
Used by ATs to query accessibility information
smashingmagazine.com/2015/03/web-accessibility-with-accessibility-api/
Define how role, state, properties, and keyboard focus are handled in the browser
An element may be supported in a browser, but not accessibility supported
Go to:
alphagov.github.io/a11y-dev-workshop/exercise4
Go to:
alphagov.github.io/a11y-dev-workshop/exercise5
A single interactive component that lets a user show or hide content. Typically it is closed (collapsed) by default.
"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"
The disclosure component must:
Write accessibility acceptance criteria relating to focus
The disclosure control must:
Write accessibility acceptance criteria relating to interaction
The disclosure control must:
Write accessibility acceptance criteria relating to appearance
The disclosure control must:
Write accessibility acceptance criteria relating to state
The disclosure control must:
Go to:
alphagov.github.io/a11y-dev-workshop/exercise6
The disclosure control does not:
The disclosure control does not:
Things mentioned during the workshop:
github.com/alphagov/a11y-dev-workshop/bllob/gh-pages/references.md