Make Your Widgets Sing with ARIA WDCNZ 25 July 2013 Jason Kiss @jkiss

Make Your Widgets Sing with ARIA Introduction to ARIA widgets

It's in the HTML Roles, states, and properties

Basic keyboard accessibility <h3>Types of pet</h3> <ul> <li><a href="/cat/">cat</a></li> <li><a href="/dog/">dog</a></li> <li><a href="/kunekune/">kunekune</a></li> </ul> <form> <fieldset> <legend>Do you like cats?</legend> <input type="radio" name="cats" id="yes" value="yes" checked> <label for="yes">Yes</label> <input type="radio" name="cats" id="no" value="no"> <label for="no">No</label> </fieldset> <input type="submit" value="Submit"> </form> Types of pet cat

dog

kunekune



Do you like cats? Yes

No

And that's important

First, there's the DOM

Accessibility APIs Mac OS Mac OS X Accessibility Protocol Windows MSAA

IAccessible2

UI Automation Linux ATK

AT-SPI

Inspecting the Accessibility APIs Windows AViewer

Accessibility Probe

Inspect Objects (MS Windows SDK) Mac OS Accessibility Inspector (Xcode) Linux Accerciser

Demo: Mac Accessibility Inspector Types of pet cat

dog

kunekune



Do you like cats? Yes

No

Still, there's the DOM Useful when: the API does not support certain information, or

the information passed to the API is incomplete

Native vs. Custom Widgets Example: Checkbox (1/3) <input type="checkbox" id="dogs"...> <label for="dogs">Dogs</label> <div class="checkbox">Dogs</div> $('.checkbox').on('click', function() { $(this).toggleClass('checked'); }); .checkbox { background: white url(../img/checkbox.png) no-repeat 0 8px; } .checkbox.checked { background-image: url(../img/checkbox-checked.png); }

Dogs



Dogs



No keyboard access. No role or state information.

It's just attributes and values roles use @ role , e.g. role="navigation"

use @ , e.g. states and properties use @ aria-* ,

e.g. aria-expanded="true" It's part of the HTML5 specification.

Landmark roles application

banner

complementary

contentinfo

form

main

navigation

search http://www.w3.org/TR/wai-aria/ Document structure roles article

columnheader

definition

directory

document

group

heading

img

list

listitem

math

note

presentation

region

row

rowheader

separator

toolbar

Native ARIA semantics header → “banner” role, if not a child of section or article

→ “banner” role, if not a child of or nav → “navigation” role

→ “navigation” role main → “main” role

→ “main” role aside → “complementary” role

→ “complementary” role footer → “contentinfo” role, if not a child of section or article

Standalone widget roles alert

alertdialog

button

checkbox

dialog

gridcell

link

log

marquee

menuitem

menuitemcheckbox

menuitemradio

option progressbar

radio

scrollbar

slider

spinbutton

status

tab

tabpanel

textbox

timer

tooltip

treeitem Composite widget roles combobox

grid

listbox

menu

menubar

radiogroup

tablist

tree

treegrid http://www.w3.org/TR/wai-aria/roles#widget_roles

Native ARIA semantics button → “button” role

→ “button” role input type="checkbox → “checkbox” role

→ “checkbox” role input type="radio" → “radio” role

Overriding native HTML semantics <a href="#">Link</a> <a href="#" role="button">Button</a> Link



Button



<ul> <li role="button">list item button</li> </ul> list item button

States and properties

Widget attributes aria-autocomplete

aria-checked (state)

(state) aria-disabled (state)

(state) aria-expanded (state)

(state) aria-haspopup

aria-hidden (state)

(state) aria-invalid (state)

(state) aria-label

aria-level

aria-multiline

aria-multiselectable

aria-orientation

aria-pressed (state)

(state) aria-readonly

aria-required

aria-selected (state)

(state) aria-sort

aria-valuemax

aria-valuemin

aria-valuenow

aria-valuetext Live region attributes aria-atomic

aria-busy (state)

(state) aria-live

aria-relevant Drag-and-drop attributes aria-dropeffect

aria-grabbed (state) Relationship attributes aria-activedescendant

aria-controls

aria-describedby

aria-flowto

aria-labelledby

aria-owns

aria-posinset

aria-setsize http://www.w3.org/TR/wai-aria/states_and_properties#state_prop_taxonomy

Managing keyboard focus tabindex="0"

Adds an element to the Tab order at its position in the source order.

Adds an element to the order at its position in the source order. tabindex="-1"

Removes an element from the Tab order.

Makes non-focusable elements programmatically focusable.

Removes an element from the order. Makes non-focusable elements programmatically focusable. tabindex="1+" (Avoid)

Specifies an element's position following the default Tab order.

role="presentation" Removes an element's default semantics. <h3>Level 3 heading</h3> Level 3 heading <h3 role="presentation">Not a heading</h3> Not a heading <table> <caption>Layout table</caption> <tr><td>Name:</td><td>Jonas Salk</td></tr> <tr><td>Discovery:</td><td>Polio vaccine</td></tr> </table> Layout table Name: Jonas Salk Discovery: Polio vaccine <table role="presentation"> <caption>Not a table</caption> <tr><td>Name:</td><td>Jonas Salk</td></tr> <tr><td>Discovery:</td><td>Polio vaccine</td></tr> </table> Not a table Name: Jonas Salk Discovery: Polio vaccine

Not on focusable elements Don't do this! It won't work anyway. <a href="#" role="presentation">Still a link!</a> Still a link! <button role="presentation">Still a button!</a> Still a button!

Example: Checkbox (1/3) revisited <div class="checkbox">Dogs</div> $('.checkbox').on('click', function() { $(this).toggleClass('checked'); }); .checkbox { background: white url(../img/checkbox.png) no-repeat 0 8px; } .checkbox.checked { background-image: url(../img/checkbox-checked.png); }

Dogs



No keyboard access. No role or state information.

Example: Checkbox (2/3) Add keyboard support add tabindex="0" <div class="checkbox" tabindex="0">Dogs</div> add handler for Space key $('.checkbox').on('click', function() { $(this).toggleClass('checked'); }); $('.checkbox').keydown(function(e) { if (e.which == 32) { $(this).click(); } });

Dogs



Still no role or state information.

Example: Checkbox (3/3) Add role and state add role="checkbox" and @ aria-checked <div class="checkbox" tabindex="0" role="checkbox" aria-checked="false">Dogs</div> add toggle for @ aria-checked $('.checkbox').on('click', function() { if ($(this).attr('aria-checked') == 'false') { $(this).attr('aria-checked', 'true'); } else { $(this).attr('aria-checked', 'false'); } }); $('.checkbox').keydown(function(e) { if (e.which == 32) { $(this).click(); } });

Dogs



Role and state provided.

Example: range slider (1/3) input type="range" <label for="slider"> Percentage (multiples of 10) </label> <input id="slider" type="range" min="0" max="100" step="10" value="0"> Supported in Opera, Safari, Chrome, IE10,

and FF23 (6 August 2013).

Otherwise falls back to input type="text" .

Percentage (multiples of 10)

Value:



Example: range slider (2/3) Custom slider with JavaScript <div>Percentage (multiples of 10)</div> <div class="slider-widget"> <div id="slider" tabindex="0"></div> </div> Keyboard accessible with tabindex="0"

and handlers for left arrow and right arrow .

No programmatic label.

No role or state information.

Percentage (multiples of 10) Value:



Example: range slider (3/3) Custom slider with JavaScript plus ARIA add role="slider" associate the label using @ aria-labelledby add required ARIA attributes dynamically update @ aria-valuenow

and @ aria-valuetext <div id="slider-label"> Percentage (multiples of 10) </div> <div class="slider-widget"> <div id="slider" tabindex="0" role="slider" aria-labelledby="slider-label" aria-valuemin="0" aria-valuemax="10" aria-valuenow="0" aria-valuetext="0%"></div> </div> Label, role and state provided.

Percentage (multiples of 10) Value:



Labels and descriptions @ aria-labelledby <div id="label">Date</div> <input type="text" aria-labelledby="label format"> <span id="format">DD-MM-YYYY</span> Date DD-MM-YYYY

Labels and descriptions @ aria-label <nav role="navigation" aria-label="Main menu"> <ul> … </ul> </nav> Home

Articles

Contact us <button aria-label="Close">X</button> X

Labels and descriptions @ aria-describedby <label for="comment">Leave a comment</label> <textarea id="comment" aria-describedby="notice"> </textarea> <p id="notice">Note: Your comment may be published.</p> Leave a comment Note: Your comment may be published.

Tabs: Role, state, and keyboard add ARIA attributes and tabindex script appropriate keyboard interaction <ul role="tablist"> <li role="presentation"> <a role="tab" aria-controls="panel-cat" aria-selected="true" tabindex="0" href="#cat">Cat</a> </li> <li role="presentation"> <a role="tab" aria-controls="panel-dog" aria-selected="false" tabindex="-1" href="#dog">Dog</a> </li> <li role="presentation"> <a role="tab" aria-controls="panel-horse" aria-selected="false" tabindex="-1" href="#horse">Horse</a> </li> </ul> <div id="panel-cat" role="tabpanel" aria-labelledby="cat"> <h3 id="cat">Man with cat</h3> … </div> <div id="panel-dog" role="tabpanel" aria-labelledby="dog"> <h3 id="dog">Man with dog</h3> … </div> <div id="panel-horse" role="tabpanel" aria-labelledby="horse"> <h3 id="horse"> Horse and bridal party </h3> … </div>

Live regions aria-live="assertive/polite/off"

aria-atomic="true/false"

aria-relevant="additions/removals/text/all" *Click "Users online" heading below to start/stop demo. <h3>Users online</h3> <ul aria-live="polite" aria-relevant="additions removals"> </ul> Users online

Types of live regions role="alert" Default is aria-live="assertive" . Make someone happy with this stunning 87 piece bracelet.

All yours for just $24.99.

Buy now!

Things I didn't cover role="application"

role="menu"

role="menubar"

role="tree"

role="grid"

role="treegrid"

role="alertdialog"

role="spinbutton"

role="progressbar" aria-hidden

aria-required

aria-expanded

aria-activedescendant

aria-haspopup

aria-dropeffect

aria-invalid

aria-pressed

aria-level ...and more

Good news Browser and screen reader support is improving all the time. Good support for structural roles and many common widgets and attributes.

Not so good news Still lots of variability in browser and screen reader support,

especially for complex widgets.

Due diligence Do the research, as you do…

Rules of engagement http://www.w3.org/TR/wai-aria/ http://www.w3.org/TR/wai-aria-practices/

Rules of engagement http://www.w3.org/TR/aria-in-html/

Using WAI-ARIA in HTML First rule of ARIA use Use native HTML elements and attributes as much as possible. Second rule of ARIA use Don't override native HTML semantics, unless absolutely necessary.