Introduction
Building your own UI controls*
gives you freedom to experiment and to design the controls to
meet your client's needs. With a little knowledge of HTML, CSS
and JavaScript, it is really quite easy.
Table of Contents
- Why assistive technology matters!
- Assistive technology and Web 2.0
- ARIA roles, properties and states
- Basic principles and how to get started
- Examples with markup/style/script walkthoughs
- Concluding remarks
- Pointers to source code
* Or you could use existing libraries such as
Dojo and
jQuery
Why assistive technology matters!
- Legal requirement to comply with current web
accessibility legislation
- Ensuring all your customers can access your
goods and services online - good business sense!
- Users with disabilities use Web sites in a different
way than the developer may expect
- Output as speech, braille, alternate colours, large size, etc.
- Input as pointer only, keyboard only, sip-and-puff, wands, speech, etc.
- See types
of assistive technology products
Assistive technology and Web 2.0
- Native apps and Web 1.0, basic accessibility
- Operating system exposes API for connecting
assistive technology
- Works effectively with Graphical user interfaces built
from operating system supplied components
- Browsers interface HTML forms controls to this API
- Problems introduced by Web 2.0 and scripting
- UI controls created with a mix of HTML, CSS and JavaScript
- Browser has no idea of author's intent
- Unusable with assistive technology
- How to get authors to provide cues that browsers
can interpret to restore a decent level of accessibility?
ARIA roles, properties and states
"WAI-ARIA, the Accessible Rich Internet
Applications Suite, defines a way to make Web content and Web
applications more accessible to people with disabilities. It
especially helps with dynamic content and advanced user interface
controls developed with Ajax, HTML, JavaScript, and related
technologies."
- Additional markup attributes to provide missing cues
- Roles for controls, e.g. tree, menubar, slider
- Static properties, e.g. reference to element with the
control's description
- Dynamic states, e.g. current position of slider
Design choice
- Allow tab to shift focus within control, e.g. days in calendar
- Or restrict tab key for moving between controls and not inside them
- Indicate "focus" with visual cues and aria-activedescendant
Basic principles and how to get started
To create an ARIA widget you should follow:
- Pick the widget type (role) from the WAI-ARIA taxonomy
- WAI-ARIA provides a role taxonomy ([ARIA], Section 3.4)
constituting the most common UI component types. Choose
the role type from the provided table.
- From the role, get the list of supported states and properties
- Once you have chosen the role of your widget, consult the
WAI-ARIA specification [ARIA] for an in-depth definition for
the role to find the supported states, properties, and other
attributes.
- Set the role, states and properties as appropriate
- Note that the states should change to reflect the current
state of the control, e.g. valuenow for a slider
These three steps need to be repeated for the children of
the parent element.
General UI guidelines
- Try to provide markup that will work if the user
has turned off scripting
- Use server-side scripts to compensate (form submissions)
- Web page scripts can change the markup as needed when page
loads, including adding all of the ARIA attributes
- Bind keys to common operations consistently
- Escape hide control without performing action
- Home/End move to the start/end of the control's range
- Page Up/Down move up/down a chunk, e.g. months in a data picker
- Arrow keys move one step in each direction
- Enter apply control's action, hiding the control if appropriate
- Tab move between controls (+Shift for backwards)
- Keep tabbing sequence simple, avoid excess tab sequences
- tabindex "0" but tabindex "-1" to exclude from sequence
- aria-activedescendant and visual cues
Coding Conventions
Minimise use of globals by defining libraries as objects, e.g.
rating.js
var aria_controls_rating = {
black_star: "★",
white_star: "☆",
rating_id: 1, // used for label id
enter: function () {
// initialization code
},
leave: function () {
// clean up code
},
key: function (event) {
// key stroke handling
}
};
aria_controls_misc.setup(aria_controls_rating.enter, aria_controls_rating.leave);
You also need to include the following in the head:
<link href="controls/controls.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="controls/common.js"></script>
<script type="text/javascript" src="controls/rating.js"></script>
- Menubar + drop down menus
- Markup as nested UL element with A for menu items
- Script adds ARIA roles, properties and states
- Use of following ARIA roles, properties and states
- role="menubar"
- role="menu"
- role="menuitem"
- aria-labeledby
- aria-haspopup
- Should aria-activedescendant be used instead of moving the focus?
- Used for browsing collections of web pages, etc.
- Markup as nested UL element with SPAN for node labels
- Easy to add icons and supplemental information
- Script adds ARIA roles, properties and states
- Use of following ARIA roles, properties and states
- role: "tree", "treeitem"
- aria-labeledby, aria-activedescendant, aria-expanded, aria-level
- Could be extended to support
- Moving nodes arround the tree (drag, shift+arrow key)
- Inserting, deleting and renaming nodes
- Disabled nodes (not perceivable by user)
Example: Tree browser
- One
- One.one
- One.one.one
- One.one.two
- One.one.three
- One.two
- One.two.one
- One.two.two
- One.two.three
- Two
- Two.one
- Two.one.one
- Two.one.two
- Two.one.three
- Three
- Three.one
supplemental info
- Three.one.one
- Three.one.two
- Three.one.three
The markup for the tree is:
<ul class="tree">
<li><span>One</span>
<ul>
<li><span>One.one</span>
<ul>
<li><span>One.one.one</span></li>
<li><span>One.one.two</span></li>
<li><span>One.one.three</span></li>
</ul>
</li>
<li><span>One.two</span>
<ul>
<li><span>One.two.one</span></li>
<li><span>One.two.two</span></li>
<li><span>One.two.three</span></li>
</ul>
</li>
</ul>
</li>
<li class="expanded"><span>Two</span>
<ul>
<li><span>Two.one</span>
<ul>
<li><span>Two.one.one</span></li>
<li><span>Two.one.two</span></li>
<li><span>Two.one.three</span></li>
</ul>
</li>
</ul>
</li>
<li><span>Three</span>
<ul>
<li><span>Three.one</span>
<span class="supplemental">supplemental info</span>
<ul>
<li><span>Three.one.one</span></li>
<li><span>Three.one.two</span></li>
<li><span>Three.one.three</span></li>
</ul>
</li>
</ul>
</li>
</ul>
- All user to pick a date from a pop-up calendar
- Markup as label + input element with type="date"
- Script adds pop-up table, ARIA roles, properties and states
- Complexity of tables, days, weeks, months and leap years
- Use of following ARIA roles, properties and states
- role: "grid", "gridcell", "columnheader"
- aria-labeledby
- aria-haspopup
- aria-owns
- Key bindings
- Page Up/Down prev/next months, Home/End for first/last day in
month, Enter and Escape as expected
- Could be extended for date ranges and use of shift
+ Page Up/Down on years
Concluding Remarks
Dive in, the water is warm!
- Further reading
- Testing and validation
- These slides are available at:
- Encourage feedback as a way of improving quality
Quirks
Browsers vary in their interoperability
- Internet Explorer needs extra care if you want controls to work in IE6+
- this can often be hidden in the implementation of methods for common
actions, e.g. script initialization, and event handler exit behaviors
- Opera has a few quirks that need special attention
- Opera selects the anchor's text when it gets the focus (after
tabbing to it), and I have yet to find an effective recipe to deselect the text
- key event handling is different from other browsers, e.g.
preventDefault doesn't work onkeydown and needs to be called onkeypress
- No support for document.contentType, at least in Opera 9.64
Support both text/html and application/xhtml+xml
- Some basic things to watch out for
Source Code
Released under W3C's MIT style document and software license
to encourage re-use. Also available under LGPL, contact Dave Raggett
<dsr@w3.org> for any questions, comments or updates.
- Rating Control
- HTML,
JavaScript,
CSS
- Menubar Control
- HTML,
JavaScript,
CSS
- Tree Control
- HTML,
JavaScript,
CSS
- Date Picker Control
- HTML,
JavaScript,
CSS
- Shared
- JavaScript