WDCNZ
25 July 2013
<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>

<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);
}
No keyboard access.
No role or state information.
role, e.g. role="navigation"aria-*, aria-expanded="true"It's part of the HTML5 specification.
applicationbannercomplementarycontentinfoformmainnavigationsearcharticlecolumnheaderdefinitiondirectorydocumentgroupheadingimglistlistitemmathnotepresentationregionrowrowheaderseparatortoolbarheader → “banner” role, if not a child of section or articlenav → “navigation” rolemain → “main” roleaside → “complementary” rolefooter → “contentinfo” role, if not a child of section or articlealertalertdialogbuttoncheckboxdialoggridcelllinklogmarqueemenuitemmenuitemcheckboxmenuitemradiooptionprogressbarradioscrollbarsliderspinbuttonstatustabtabpaneltextboxtimertooltiptreeitemcomboboxgridlistboxmenumenubarradiogrouptablisttreetreegridbutton → “button” roleinput type="checkbox → “checkbox” roleinput type="radio" → “radio” role
<a href="#">Link</a>
<a href="#" role="button">Button</a>
<ul>
<li role="button">list item button</li>
</ul>
aria-autocompletearia-checked (state)aria-disabled (state)aria-expanded (state)aria-haspopuparia-hidden (state)aria-invalid (state)aria-labelaria-levelaria-multilinearia-multiselectablearia-orientationaria-pressed (state)aria-readonlyaria-requiredaria-selected (state)aria-sortaria-valuemaxaria-valueminaria-valuenowaria-valuetextaria-atomicaria-busy (state)aria-livearia-relevantaria-dropeffectaria-grabbed (state)aria-activedescendantaria-controlsaria-describedbyaria-flowtoaria-labelledbyaria-ownsaria-posinsetaria-setsizehttp://www.w3.org/TR/wai-aria/states_and_properties#state_prop_taxonomy
tabindex="0"tabindex="-1"tabindex="1+" (Avoid)role="presentation"Removes an element's default semantics.
<h3>Level 3 heading</h3>
<h3 role="presentation">Not a heading</h3>
<table>
<caption>Layout table</caption>
<tr><td>Name:</td><td>Jonas Salk</td></tr>
<tr><td>Discovery:</td><td>Polio vaccine</td></tr>
</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>
| Name: | Jonas Salk |
| Discovery: | Polio vaccine |
Don't do this!
It won't work anyway.
<a href="#" role="presentation">Still a link!</a>
<button role="presentation">Still a button!</a>
<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);
}
No keyboard access.
No role or state information.
tabindex="0"
<div class="checkbox" tabindex="0">Dogs</div>
$('.checkbox').on('click', function() {
$(this).toggleClass('checked');
});
$('.checkbox').keydown(function(e) {
if (e.which == 32) {
$(this).click();
}
});
Still no role or state information.
role="checkbox" and @aria-checked
<div class="checkbox" tabindex="0"
role="checkbox" aria-checked="false">Dogs</div>
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();
}
});
Role and state provided.
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".
<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.
role="slider"aria-labelledbyaria-valuenowaria-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.
aria-labelledby
<div id="label">Date</div>
<input type="text" aria-labelledby="label format">
<span id="format">DD-MM-YYYY</span>
aria-label
<nav role="navigation" aria-label="Main menu">
<ul>
…
</ul>
</nav>
<button aria-label="Close">X</button>
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>
Note: Your comment may be published.
<ul>
<li><a href="#cat">Cat</a></li>
<li><a href="#dog">Dog</a></li>
<li><a href="#horse">Horse</a></li>
</ul>
<div>
<h3 id="cat">Man with cat</h2>
...
</div>
<div>
<h3 id="dog">Man with dog</h2>
...
</div>
<div>
<h3 id="horse">Horse and bridal party</h2>
...
</div>
<ul class="tablist">
<li class="current"><a href="#cat">Cat</a></li>
<li><a href="#dog">Dog</a></li>
<li><a href="#horse">Horse</a></li>
</ul>
<div class="tabpanel" style="display: block;">
<h3 id="cat">Man with cat</h2>
...
</div>
<div class="tabpanel" style="display: none;">
<h3 id="dog">Man with dog</h2>
...
</div>
<div class="tabpanel" style="display: none;">
<h3 id="horse">Horse and bridal party</h2>
...
</div>
No role or state information provided.
tabindex
<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>
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>
role="alert"Default is aria-live="assertive".
Make someone happy with this stunning 87 piece bracelet.
All yours for just $24.99.

role="application"role="menu"role="menubar"role="tree"role="grid"role="treegrid"role="alertdialog"role="spinbutton"role="progressbar"aria-hiddenaria-requiredaria-expandedaria-activedescendantaria-haspopuparia-dropeffectaria-invalidaria-pressedaria-level...and more
Browser and screen reader support is improving all the time.
Good support for structural roles and many common widgets and attributes.
Still lots of variability in browser and screen reader support,
especially for complex widgets.
Do the research, as you do…
http://www.w3.org/TR/wai-aria/
Use native HTML elements and attributes as much as possible.
Don't override native HTML semantics, unless absolutely necessary.