Summary
Update
Please note: this article is now out of date. See the following for more details.
The Web Accessibility Initiative's Accessible Rich Internet Applications (WAI-ARIA) roadmap includes a plan for developing the roles and states necessary to make rich internet applications accessible. The accessible properties are added using the namespacing capabilities of user agents that support XHTML delivered as application/xhtml+xml
. As Internet Explorer doesn't support this MIME type, it cannot make use of namespacing in the markup. To make up for this, WAI's protocols and formats working group have a document outlining how to add WAI-ARIA roles and states to HTML content delivered as text/html
.
The technique essentially serialises the role and state information in the class
attribute. HTML user agents don't parse namespace information, but as the DOM API supports namespaces, the role and state information can be inserted with the namespace directly in the DOM so that HTML documents delivered as text/html
can use WAI-ARIA roles and states. The protocols and formats working group provide an ECMAScript library to insert the information specified in the class
atttibute into the DOM.
Author: Gez Lemon
Contents
- Document Semantics
- A Touch of Class
- Using Namespaced Attributes in HTML
- Specifying the
class
Values - Multiple Roles
- Progressive Enhancement
- WAI-ARIA Support
Document Semantics
The problem with developing rich internet applications in HTML for the web is that HTML (and XHTML 1.x) only has a small set of semantic elements. Assistive technologies communicate information to the user based on document semantics. When developers create custom controls, accessibility problems can be introduced if the controls do not have the correct semantics to inform assistive technology what the control is and what values it has.
WAI's Accessible Rich Internet Applications (WAI-ARIA) roadmap includes a plan for developing the roles, and states and properties necessary to make RIAs accessible. WAI-ARIA does this using the namespace capabilities of XHTML, which isn't supported in HTML. Also, XHTML documents must be served as application/xhtml+xml
in order to use XHTML's namespace capabilities; if XHTML documents are delivered as text/html
, the user agent will treat it as HTML, and the namespace information will be lost. This means that user agents that don't understand content delivered as application/xhtml+xml
, such as Internet Explorer, can't make use of the roles and states defined in the WAI-ARIA roadmap.
A Touch of Class
A note on WAI's protocols and formats website explains an approach for embedding accessibility role and state metadata in HTML documents (editor's draft). The technique allows content to be served as text/html
, which means WAI-ARIA role and state information can be provided for user agents that can't handle content delivered as application/xhtml+xml
.
The technique works by specifying role and state information in the class
attribute, as the class
attribute applies to all elements in the strict doctype, except the base
, head
, html
, meta
, param
, script
, style
, and title
elements. An ECMAScript library, enable.js, can then used to insert the accessibility information in the appropriate role and state namespaces.
Using Namespaced Attributes in HTML
User agents that parse HTML don't parse namespace information, but the namespace information can be inserted into the DOM, as the DOM API does support namespaces. XHTML served as application/xhtml+xml, can use namespace aware methods from the Document Object Model (DOM) Level 2 Core Specification, such as setAttributeNS
. Some browsers don't support the namespace methods, and must instead use the methods from Document Object Model (DOM) Level 1 Specification, such as setAttribute
, which isn't namespace aware. When using the non-namespace aware methods, the namespace value must be prefixed to the attribute name. So developers could do something like the following to use namespace DOM methods when they are supported, or use the HTML hack to prefix the namespace value to the attribute name:
if (typeof document.documentElement.setAttributeNS != 'undefined')
{
oElm.setAttributeNS('http://www.w3.org/2005/07/aaa', 'valuenow', 3);
}
else
{
oElm.setAttribute('aaa:valuenow', 3);
}
Fortunately, the logic is taken care of in enable.js — all the developer has to do is specify the role and state information in the class
attribute, and call the initApp
method when the page is loaded, and the initContent
method if rich content is added after the initApp
method has executed.
Specifying the class
Values
The class
attribute accepts a space separated list of class names. To specify role and state information in the class
attribute, a class name of axs
is used — the values that follow the class name axs
are the role and states for the control. This means that a class name of axs
should be avoided for general styling by developers using this technique to add WAI-ARIA accessibility information, as it has a specific meaning in the ECMAScript library. The first class name following the class name axs
is the role; the rest of the class names are the state information. This means that developers must ensure that all classes used as hooks for CSS selectors, or other programmatic hooks, are placed before the axs
class name.
The state information is a key/value pair, separated by a hyphen. The following example shows how the class
attribute might be used to set WAI-ARIA role and state information for a slider control:
<input type="image"
src="thumb.gif"
alt="Effectiveness"
id="thumb"
title="Effectiveness, between 0 and 500"
class="axs slider valuemin-0 valuemax-500 valuenow-3">
For states that accept a value of true
, the value can be omitted if the state is true
, as this is the default value for these states. For example, the following two classes have equivalent values:
class="axs checkbox checked-true"
class="axs checkbox checked"
Multiple Roles
As the first value specified as a class name following the axs
class name is the role, and the rest of the class names describe the state, this means that only one role can be specified using this technique. Using XHTML namespaces, more than one role may be specified. Embedding accessibility role and state metadata in HTML documents states that whilst it is common for there to be more than one state, it's very rare to require more than one role. If more than one role is required, it would be possible by reworking enable.js so that the roles were specified with a separator, such as a colon:
class="axs table:tree ..."
Progressive Enhancement
enable.js is a clever solution for creating rich internet applications, but I prefer to use content negotiation and progressive enhancement. For example, instead of starting off trying to define a slider control in markup, start with an element that is semantically as close to the control you're trying to make richer; in this case, a drop-down list: Use content negotiation to determine if the user agent can handle content delivered as application/xhtml+xml
: If the user has a script enabled browser, use progressive enhancement to update the drop-down list to a slider control, and use the same keystrokes required to interact with the slider that the drop-down list would use. See the slider control for an example of how this is done in practice.
WAI-ARIA Support
At this time, the only user agent that supports WAI-ARIA is Firefox (1.5 and higher). Assistive technology, such as JAWS and Window-Eyes, are able to communicate role and state information specified with ARIA, and the situation will get better as more work is put into the specification, and other user agent start to support ARIA. Charles Chen's excellent Fire Vox plugin has added support for ARIA, and Opera are also working on adding support for ARIA. Hopefully, Internet Explorer, Safari, and other user agents also have WAI-ARIA on their radars.
The slider control works as expected in Internet Explorer with JAWS and Window-Eyes because the custom control has an explicit label, and the role is exposed through the alt
attribute of the input
element.
Category: Accessibility.
[wai-aria-in-html.php#comment1]
The enable.js library should be updated to facilatate using WAI-ARIA markup when there is no role, e.g. you just want to make an HTML input required, or use live region markup, etc.
Posted by Aaron Leventhal on
[wai-aria-in-html.php#comment2]
Hi Aaron,
You could use something similar to the technique I suggested for allowing multiple roles. Instead of just using a colon as a separator, you could append it to all roles, so it's clear whether something is a role or a state. For example, the following could be used to specify one role and one state:
The following could be used to specify two roles:
There could be a space between the two roles if all roles are appended an identifier, such as a colon. Class names that follow the
axs
that don't have a colon at the end are just states. For example:Posted by Gez on
[wai-aria-in-html.php#comment3]
I always feel that using the class attribute is a dirty hack. Especially now Visual Studio (2008) underlines classnames and says "I can't find this class in any of your CSS files, are you sure you typed it right?"!
In VB (and .NET) lots of classes have a "Tag" propery which just lets you put your own crap in there. Slightly less "hacky" than hijacking the class attribute, but still not ideal.
If you created a class called "required" to style your asterisks in forms, then later following the above sample added it to your textbox, you might get strange issues that aren't completely obvious at first. It just seems a bit of a fudge! :/
Posted by Danny Tuppeny on
[wai-aria-in-html.php#comment4]
Hi Danny,
The proposed technique is a hack to insert namespaced attributes into the DOM, but it's not a dirty hack to use the
class
attribute. The purpose of the class attribute is to allow programmatic access to elements that belong to a certain class; from the HTML 4.01 element identifiers section:Posted by Gez on
[wai-aria-in-html.php#comment5]
There's no reason why the NS methods can't be used in HTML. The setAttribute() method will insert an attribute in no namespace, which is the same as attributes specified in the markup in HTML. enable.js checks whether setAttributeNS() is supported before using it, rather than checking if the document is an XML document.
Posted by zcorpan on
[wai-aria-in-html.php#comment6]
Thank you for the clarification, zcorpan. I've updated the part where I incorrectly stated that HTML documents served as
text/html
had to use methods from the DOM 1 specification.I realised that enable.js was feature sniffing to determine which method to use. For those not using enable.js and using content negotiation, it's presumably okay to check for the existence of
document.xmlVersion
instead of feature sniffing, as it wouldn't be set if the user agent couldn't acceptapplication/xhtml+xml
? As enable.js primarily exists for content served astext/html
, it makes sense for them to use feature sniffing instead, as thexmlVersion
property wouldn't be set.Thanks again for the clarification.
Posted by Gez on
[wai-aria-in-html.php#comment7]
From the DOM point of view, it's just a set of nodes, and it doesn't really matter if they came from parsing HTML, parsing XML, or from script. The NS methods are available in all cases and do the same things.
You want to use the NS method even in text/html, if it's supported, because setAttribute() doesn't do the right thing (the attribute ends up in no namespace).
Posted by zcorpan on
[wai-aria-in-html.php#comment8]
Hi zcorpan,I understand that part. What I meant was if content negotiation is used, wouldn't a browser that supports namespaced methods have
application/xhtml+xml
in its accept headers, or is that too big an assumption? If that assumption is incorrect, I'll update the script I'm using to use feature sniffing instead, as it would still work regardless of MIME type.Posted by Gez on
[wai-aria-in-html.php#comment9]
It's probably an inaccurate assumption. Some versions of Firefox prefer text/html over application/xhtml+xml, IIRC.
Posted by zcorpan on
[wai-aria-in-html.php#comment10]
Thanks, zcorpan; I'll update the scripts, as the assumption isn't correct. Aaron mentioned that Firefox had changed its accept header to indicate it preferred
text/html
overapplication/xhtml+xml
with the quality parameter, but that it still handledapplication/xhtml+xml
okay. As it won't hurt to use feature sniffing, I'll update the scripts accordingly.Thanks again for your help.
Posted by Gez on
[wai-aria-in-html.php#comment11]
zcorpan - this is not only a FireFox bug but also Opera and Safari for windows prefer text/html so thats why, I have sometimes accessibility problems when I visit new websites from Opera or Safari but I don't have many problems with IE).
Regards
Posted by Tomasz Gorski on
[wai-aria-in-html.php#comment12]
It seems that this particular slider example risks diabetes, stroke, and other conditions one suffers from being overweight. Would not a simple text input suffice as the basis of our progressive enhancement?
Posted by russ on
[wai-aria-in-html.php#comment13]
You can use whatever element is the most appropriate for the basis of progressive enhancement. I chose a drop-down list because the user can type the number directly, or use the same keystrokes (page up, page down, home, end, and cursor keys) as the slider control to set the value without requiring extra validation to ensure the value is a number between 0 and 500.
Posted by Gez on
[wai-aria-in-html.php#comment14]
Please note that this article was written before a new, simpler way for using ARIA in
text/html
was devised.Mozilla, Opera and the HTML working group worked together to develop the new solution, which is available in Firefox 3 test builds since September 25.
It's being developed into a more formal specification.
Posted by Aaron Leventhal on