You're only supposed to blow the bloody doors off!
You're only supposed to blow the bloody doors off!
Nordic.JS, Stockholm September 2017
You're only supposed to blow the bloody doors off!
Screen reader demo: headings
Screen reader demo: forms
Keyboard intercept chain
- Windows
- Screen reader
- Browser
- Mac OS
- Browser
- Screen reader
Virtual/browse mode
Windows screen readers create a virtual copy of the browser contents
Forms/focus mode
Windows screen readers pass keys straight through to the browser
JavaScript keyboard shortcuts
JavaScript keyboard shortcuts: problem
JavaScript keyboard shortcuts: solution
- Make JavaScript shortcuts an enhancement (not a primary function)
- Make the primary function usable
Platform controls
- Role
- checkbox
- Name
- Bold
- State
- Focusable, Focused, Checked
Accessibility APIs
- Windows
- UI Automation (UIA)
- MS Active Accessibility (MSAA)
- IAccessible2 (IA2)
- Mac OS
- OSX Accessibility Protocol (AXAPI)
- Linux
- Accessibility Toolkit (ATK)
- AT Service Provider Interface (AT-SPI)
Web controls
<label for="this">Bold</label>
< type="checkbox" id="this" checked>
- Role
- checkbox
- Name
- Bold
- State
- Focusable, Focused, Checked
Accessibility mappings
Define how role, state, properties, and keyboard focus for native elements are handled in the browser
DOM tree
Accessibility tree
HTML mapping support
Browsers may support an element, but not accessibility support it
A browser may accessibility support an element, but a screen reader may not
Manipulating the DOM
- Browser parses the HTML and builds the DOM
- Browser uses the DOM to build the accessibility tree
- Browser updates the DOM in response to user interaction or scripted events
- Browser responds to changes in the DOM and updates the accessibility tree
- Assistive technologies listen for changes in the accessibility tree and respond accordingly
Polyfill accessibility
When native accessibility information is unavailable
ARIA: don't use it
Use native HTML whenever possible
- Keyboard interaction
- Focus management
- Role, state, and property information
Native HTML
<button>Tequila!</button>
var button = document.getElementById('button');
button.addEventListener('click', doSomething, false);
Screen reader demo: native HTML
ARIA: unless you need to
When repurposing elements like <div>
and <span>
Missing semantics
<span id="button">Tequila!</span>
Keyboard demo: missing semantics
Screen reader demo: missing semantics
With added semantics
<span id="button" role="button" tabindex="0">Tequila!</span>
Screen reader demo: with added semantics
ARIA: don't break native semantics
<button role="heading" aria-level="1">Tequila!</button>
Screen reader demo: broken semantics
ARIA: make it work with a keyboard
When you create custom components it's your responsibility to make it work with the keyboard
Supplement existing interaction
<a href="#here" id="button" role="button">Tequila!</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">Tequila!</span>
var button = document.getElementById('button');
button.addEventListener('keydown', function(event) {
if (event.keyCode == 13 || event.keyCode == 32) {
toggle();
}
});
Screen reader demo: provide all interaction
Using the application role
<body role="application">...</body>
Removes the screen reader from the keyboard intercept chain
Roles that trigger applications mode
Many ARIA roles trigger applications mode automatically, including:
- tablist
- grid
- menu and menubar
- toolbar
Application mode: tablist
<ul role="tablist">
<li role="presentation">
<a role="tab" href="#p1" aria-selected="true" aria-controls="p1">Blanco</a>
</li>
<li role="presentation">
<a role="tab" href="#p2" aria-selected="false">Reposado</a>
</li>
...
</ul>
Screen reader demo: application mode with tablist
Keyboard focus: roving tabindex
- Set the currently selected object to tabindex="0"
- Set all other objects to tabindex="-1"
- When user navigates to next object set focus using .focus()
- Set currently selected object to tabindex="0", and all others to tabindex="-1"
Focus management example: roving tabindex
<ul role="tablist">
<li role="presentation">
<a role="tab" href="#p1" aria-selected="true" aria-controls="p1">Blanco</a>
</li>
<li role="presentation">
<a tabindex="-1" role="tab" href="#p2" aria-selected="false">Reposado</a>
</li>
...
</ul>
Keyboard interaction: event listeners
Listen for keydown and capture keycodes:
- Left 37
- Right 38
- Up 39
- Down 40
Screen reader demo: application mode with tablist and keyboard interaction
AOM: phases
- Modify accessibility node semantics
- Respond to events from screen readers (and other ATs)
- Create virtual accessibility nodes
- Query the accessibility tree
You're only supposed to blow the bloody doors off!
Thank you