Time traveller's guide to accessibility mechanics

Léonie Watson

Time traveller's guide to accessibility mechanics

BristolJS, Bristol February 2019

Léonie Watson, TetraLogical

Browsers

Chrome Edge Firefox Safari
Chrome Edge Firefox Safari
(Google) (Microsoft) (Mozilla) (Apple)

Screen readers

Jaws NVDA Voiceover Narrator Orca
Jaws NVDA Voiceover Narrator Orca
(Freedom Scientific) (NV Access) (Apple) (Microsoft) (GNOME)

Past...

In the 1990s

Screen readers consumed the HTML directly from the browser, and created a virtual model of the content

Demo: reading text

By the 2000s

Screen readers began using platform accessibility APIs to query information from the browser

Platform accessibility APIs

Windows MacOS Linux
UI Automation (UIA)
MS Active Accessibility (MSAA)
IAccessible2 (IA2)
OSX Accessibility Protocol (AXAPI) Accessibility Toolkit (ATK)
AT Service Provider Interface (AT-SPI)

The main element

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

The nav element

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

The ol element

<ol>
<li>Do this</li>
<li>Do that</li>
<li>Do something else</li>
</ol>

The h1 element

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

The checked attribute

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

Demo: the checked attribute

The button element

<button>Play</button>
Role
button
Name
Play
State
Focusable
Interaction
Click, Keyboard, Tap

Demo: the button element

Present...

Custom UI components

Neutral elements

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

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:

The span attribute

<span id="button">Play</span>
Role
Name
State

The role attribute

<span id="button" role="button">Play</span>
Role
button
Name
Play
State

The tabindex attribute

<span id="button" role="button" tabindex="0">Play</span>
Role
button
Name
Play
State
Focusable

Keyboard interaction

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

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

Demo: Custom button

The aria-pressed attribute

<span id="button" role="button" tabindex="0" aria-pressed="false">Play</span>
Role
button
Name
Play
State
Focusable, Not pressed

The functionality

var button = document.getElementById('button');

function doSomething(event) {        
    if (button.getAttribute('aria-pressed') == 'false') {
        button.setAttribute('aria-pressed', 'true');
    }
    else {
        button.setAttribute('aria-pressed', 'false');
    }
}

The CSS attribute selector

span[aria-pressed="true"] {
    color: #fff;
    padding: 11px 12px 9px 16px;
    text-shadow: 0 -1px 0 #444, 0 0 5px #ffd, 0 0 8px #fff;
    box-shadow: 0 1px 0 #666, 0 2px 0 #444, 0 2px 2px rgba(0,0,0,0.9);
}

Demo: the aria-pressed attribute

The button element

<button id="button" aria-pressed="false">Play</button>
Role
button
Name
Play
State
Focusable, Not pressed

The custom element

class tButton extends HTMLElement {
    constructor () {
        super();
        var shadow = this.attachShadow({ mode: 'open' });

        // Additional code

        shadow.appendChild(button);
    }
}
customElements.define('toggle-button', tButton);

Extending the button element

constructor () {
    ...
    var button = document.createElement('button');
    var text = this.innerHTML;

    button.classList.add('toggle-button');
    button.textContent = text;
    ...
}

The functionality

constructor () {
    ...
    function toggle(event) {
        if (button.getAttribute('aria-pressed') == 'false') {
            button.setAttribute('aria-pressed', 'true');
        }
        else {
            button.setAttribute('aria-pressed', 'false');
        }
    }
    button.addEventListener('click', toggle, false);
    ...
}

The toggle-button element

<toggle-button>Play</toggle-button>
Role
toggle-button
Name
Play
State
Focusable, not pressed

Demo: the toggle-button element

The rendered code

<toggle-button aria-pressed="false">Play</toggle-button>

Future

Accessibility Object Model (AOM)

An experimental JavaScript accessibility API:
github.com/WICG/aom

Phase 1A: ARIA reflection

Instead of:

button.setAttribute('role', 'button');
button.setAttribute('aria-pressed', 'false');

It would be:

button.role = 'button';
button.ariaPressed = 'false';

Phase 1B: Custom Element semantics

Authors will be able to:

Phase 2: User action events

Authors will be able to respond to new types of input event, including:

Phase 3: Virtual accessibility nodes

Will allow authors to create virtual accessibility tree nodes that do not map to the DOM

Phase 4: Computed accessibility tree

Will allow authors to:

Be a time traveller

Use the best...

Of the past, present, and future

Thank you!

BristolJS, Bristol February 2019

Léonie Watson, TetraLogical