OUTDATED CONTENT
Although the article below is not flat-out wrong, it's certainly an example of old-skool thinking about JavaScript and accessibility. This page concentrates on the division between script user agents and noscript user agents, while there turns out to be a middle group. See You should've been @media - part 2 under "Accessibility" for a summary of the problems we're facing.
The relation between JavaScript and accessibility has to be re-thought from the ground up. At the moment we just don't know. Please help us find out more.
The single script example on this page is outdated, too: it uses inline event handlers, which is deprecated
nowadays. Finally, I did not consider keyboard or interface events at all (onfocus as a alternative
for onmouseover, for instance), and that's something that should be taken into account, too.
A note about the external links:
All external links on this page, with the exception of those leading to W3C and Evolt, are taken from the
first three pages I got when
googling for 'JavaScript accessibility' in
March 2003. I consider them a fair sample of currently available web pages on this subject.
I am notoriously sloppy in updating links, so if you notice a dead link, please mail me.
On this page I give a short introduction to the accessibility issues surrounding
the use of JavaScript. It is by no means a complete tutorial; I just want to offer a few rough
guidelines and some bits of information.
Nonetheless the information on this page seems to be
clearer and more complete than the average "JavaScript and accessibility" page on the WWW.
Regarding JavaScript and accessibility, there are two myths:
Neither of these myths are true. As happens so often, the truth lies in the middle.
To come closer to the truth, take the last website you produced and look at it again. Then turn JavaScript off (see the Browsers pages for instructions how to do this). Reload the site and see if it still works. If you cannot access navigation or content, carefully note which JavaScript functionality causes the problem. Don't worry about solutions yet, first read this page.
Or read this story about websites that are inaccessible without JavaScript. It gives a practical example of the problems JavaScript pages can cause in a noscript browser.
This page inevitably starts with the
W3C's guidelines, followed by a discussion of the
noscript tag, which turns out not to be as useful as it seems.
Then we'll encounter the
lack of general rules that requires us to perform a lot of
case studies to study accessibility issues for important
scripts on this site. Case studies are the only correct way to solve these issues.
Events are a separate problem. This issue
is quite confused by badly thought out and sometimes contradictory guidelines on several sites.
Finally it's time for a
conclusion and some useful links.
Of course we start with the W3C WAI Guidelines:
"Ensure that pages are usable when scripts, applets, or other programmatic objects are turned
off or not supported.
If this is not possible, provide equivalent information on an alternative
accessible page."
I intensely dislike the second alternative. As soon as you create two versions of the same page you also create serious problems for the people who're going to update the site. Besides, it's simply not done.
As to the first alternative, it is perfectly logical and possible, as long as we use a practical definition of "usable". In my view, a usable site is any site that allows any visitor to read and use its content and navigation. Nothing less, but also nothing more.
W3C gives an example of dealing with scripts and accessibility, which unfortunately is somewhat marred. First of all it uses the obscure TCL scripting language that is completely irrelevant to the WWW, secondly the code is not an example of well thought-out accessibility.
In the example, the information generated by the TCL script is repeated in plain HTML.
The HTML is placed within a <noscript> to hide it from script-capable
browsers. In itself this is an excellent idea, but one does wonder why we need a script when the
information can (apparently) also be generated through a server side script. I'd remove the
script entirely and rely on server side generation exclusively.
This curious example has been uncritically copied by some sites, even though it fails to give a practical solution to any problem.
W3C's example does point to one of the principal tools for ensuring accessibility: the
<noscript> tag.
Although all "JavaScript and accessibility" pages note
the use of this tag, they are sometimes confused about its practical use.
Can the <noscript> tag solve
accessibility problems? Of course it can. But it's not the end-all of accessible sites it's
sometimes made out to be.
W3C itself is careful to note that using
<noscript> is only one way of solving accessibility problems, though
it doesn't give any details.
trace.wisc.edu maintains that a <noscript>
alternative must be added to every single script, which is obviously nonsense (how do you
provide a noscript alternative to form validation?).
Fortunately
www.webaim.org does make a distinction between useful
and useless <noscript> tags and even explains this distinction.
Basically, <noscript> can provide an alternative text for a
script, but rarely more than that. So the first question is: do you need an alternative
text? If you don't, you don't need <noscript> either.
Even if you do need alternative texts, and thus the <noscript> tag, you
may encounter problems. For instance, take this hypothetical code for a DHTML navigation:
<script>
for (var i=0;i<x.length;i++)
{
document.write('<a href="page'+i+'.html" onmouseover="doDHTML()">Link '+i+'</a>');
}
</script>
<noscript>
<a href="page1.html">Link 1</a>
<a href="page2.html">Link 2</a>
[etc]
</noscript>
Sure, this will work. The problem, however, is that you have to update the navigation in
two places, in the array x which the script uses and in the noscript alternative.
I don't like that at all, it makes for complicated sites. Besides, some judicious HTML structuring
may make <noscript> unnecessary, as we'll see below.
Concluding, <noscript> is a useful tool for solving some accessibility problems,
but its use doesn't guarantee accessibility at all. And remember that it doesn't work in Netscape 2,
so the few surviving Netscape 2 users will see both the script and the noscript versions of your
page.
Does using JavaScript make a site inaccessible? Not in and of itself. Using JavaScript for
extra functionalities is quite allowed.
It could even be argued that the <script> tag itself is an important tool
for creating accessible JavaScript pages. When adding advanced effects to your pages, you could
choose to generate the necessary HTML entirely by JavaScript. Thus you don't need noscript
messages (which tend to be rather disappointing to your users, anyway). We'll see an example of this
when we study accessible DHTML navigation.
So there's no easy good and bad.
Unfortunately most of the "Accessibility and JavaScript" pages I read are quite vague and incomplete. They prominently quote or paraphrase the W3C WAI Guidelines and speak in strong terms about the necessity of accessible pages, but mostly fail to give practical information.
A welcome exception is the NCI Web Accessibility site, which said, before it went offline:
'"Accessible" javascript techniques are still very much a work in progress; the lively debate on
developer listservs and bulletin boards will give you valuable tips, but also underscore the substantial
uncertainties that characterize this topic. Over time, best practices will emerge in the javascript community.
For now, we've attempted to summarize the known issues, workarounds, and suggestions,
but remember: everything must be tested!'
This is quite correct. There are no general rules. The only way to ensure accessibility and JavaScript living in harmony is by evaluating each individual script and devising a unique solution to the accessibility problems it poses.
Since there are no general rules, we should proceed on a case-by-case basis. Therefore I review the accessibility problems (or lack thereof) of some important scripts on this site. I hope these examples will give you some ideas of your own.
First of all we have to define the purpose of the script. Is the script required, useful or merely ornamental? In general, useful or ornamental scripts can be switched off without trouble. Required scripts cause far more problems and need some judicious accessibility enhancements.
After defining the purpose of the script I review the effects in three user agents:
Finally I take a look at the solution of the problems (if any). In general we'll see that the more advanced a script is, the more accessibility problems it causes.
No problems
Purpose of the script: Creating a nice graphical extra that makes the site more
lively. Sometimes it conveys information ("You are here").
(Script)
Solution: None necessary, as long as you make sure the mouseovers don't convey critical
information.
So it's simple. Complicated solutions like this one are quite unnecessary.
No problems
Purpose of the scripts: Show different content or to redirect users to a different
page depending on the capabilities of their browsers.
(Examples: Browser detect,
Flash detect,
Customized framesets)
Solution: Always let all users enter your site at the simplest possible page. This page may contain a script that redirects the user. If the browser can handle the script it is redirected, if it can't it stays on the simple page. No problems either way.
<script>
location.replace('page_with_javascript.html');
</script>
<p>This is the simple page. If your browser can handle it, you may
<a href="page_with_javascript.html">go on</a> to the JavaScript
enhanced page.</p>
<p>[Start of the actual content]</p>
My own site doesn't quite work that way; noscript users get a plain vanilla link leading to the homepage. But since my site is about JavaScript, I (almost) require all users to have JavaScript enabled.
No problems
Purpose of the script: Useful. It validates form entries in the most user friendly
way possible. Any form should be validated on the server, too.
(Script)
Solution: None necessary, as long as you also validate the form server-side.
Required reading: Forms & JavaScript Living Together in Harmony by Jeff Howden.
Accessibility alert
Purpose of the script: Scripts that do something with select boxes are usually meant
for navigation. Therefore we immediately flash the accessibility alert: since any browser should
be able to access the site navigation, any navigation that uses select boxes and JavaScript should
be repeated in plain links.
(Examples:
Select box navigation,
Dynamic options)
Solution: Repeat the navigation in plain links, possibly hiding them from modern
browser through the <noscript> tag. If you don't repeat the navigation, your site is inaccessible.
Another solution would be to add a Go! button that sends the form to a little server
side script to do the redirecting. Once again, you can hide this button in a <noscript>
tag.
Be careful
Purpose of the script: What is the purpose of popups...? I generally dislike them, though
I must admit that once in a very great while a popup may have a legitimate function (navigation,
extra messages). Too often they're a crutch for people who don't want to spoil their beautiful
design by inserting content.
(Script)
window.close()).Solution: Make sure that noscript browsers follow a plain link to the page shown in the popup:
function popitup(url)
{
newwindow=window.open(url,'name','height=200,width=150');
if (window.focus) {newwindow.focus()}
return false;
}
<a href="popupex.html" onClick="return popitup('popupex.html')"
>Link to popup</a>
Call the popup script from an onclick event handler which returns false.
This prevents the browser from following the actual href. Only when JavaScript is disabled
does the browser follow the link and show the popup page in the main window.
Required reading: Links & JavaScript Living Together in Harmony by Jeff Howden.
Be very careful
Purpose of the script: To provide access to all pages and to give a clear
sitemap-like overview of the structure of the site.
(Script)
Solution: The placement of the DHTML layers in your source code is of prime importance. They're traditionally placed at the top, but without JavaScript the page would start with 30 or 40 links in no apparent order, causing terrible confusion.
In general I think it's best to show the 'root' navigation at the top of the page, where noscript browsers can easily access it. The other layers, however, should be placed at the bottom of the page, so that the content starts immediately after the 'root' block and users of noscript browser immediately see it.
The only layer that may also be placed at the top is the one that shows the subnavigation of the part of the site the page is in.
Accessify suggests you should generate all navigation layers except for the 'root' block by JavaScript, because this creates better accessibility! The idea is very interesting, since users of noscript browsers would be spared seeing lots of links without context. Nonetheless this solution could lead to problems, too, since you'd have to define a second way of navigating the site without JavaScript.
Serious, insolvable problems
Purpose of the scripts: To allow the user to change (parts of) the page for better
usability or for doing something with the content.
(Examples: Edit text,
Extending forms)
Solution: None, really. W3C DOM applications won't become accessible in the near future.
A separate problem is the correct use of events. Speech browsers and mobile phones don't have a mouse, so making mouse events accessible can be quite problematical.
The general rule is that when you use events to trigger scripts, you should choose those events that are supported by as many devices as possible.
In fact, this rule has little to do with accessibility. When writing event-triggered scripts
for traditional JavaScript browsers, you should also choose those events that ensure maximum
cross-browser compatibility.
Therefore we need a good compatibility table that tells us which events are supported by which
speech browsers, mobile phones or other devices. I haven't found one as yet, and I don't have
the money to buy all the devices I should test to create this table.
Many "JavaScript and accessibility" web pages go into a flurry of activity by making rules for the events hypothetical non-traditional browsers with JavaScript enabled might (or might not) support. Although most of these rules are worth a second look, some of them are just assumptions without any practical basis.
W3C gives the following three rules:
blur, focus and select.
Device-dependent events like mouseover or keypress may not be supported
by a speech browser, which uses neither mouse nor keyboard. Interface events, though, are
device-independent. A focus event on a link takes place whenever the user goes to
a link, whether by a mouse click or by the Tab button.keydown with mousedown, keyup/mouseup,
keypress/click. Thus the script will be called when the user uses the mouse and also
when he uses the keyboard.dblclick.I agree with rules 2 and 3. Rule 2 allows users of traditional browsers to use the keyboard instead of the mouse.
Rule 3 at first sight seems to be rather restrictive, but it can be worked around easily. Usually, the purpose of a script that depends on mouse coordinates is to show something, a layer for instance, on or right next to the element the user has moused over or clicked on. When the user uses a keyboard or other navigational devices, the script won't find any mouse coordinates and would behave erratically.
Solution: don't detect the mouse coordinates. Instead, find the position of the element the user has moused over or clicked on and use these coordinates to place your layer.
As to rule 1, I'm less sure. A focus event simply isn't the same as a mouseover
event. Besides, rule 1 heavily depends on the way non-traditional devices define the various events. W3C
conservatively assumes they won't define mouse events, but why shouldn't they?
They might equate a focus event on a link with a mousedown event, since
both events are a necessary preparation for a click event on the link.
Similarly, a user hitting 'Return' when the focus is on a link also causes a sort of click
event, even though he doesn't use the mouse.
So it's all a matter of definition. Traditionally browser makers try to incorporate all code
that is in common use, and certainly mouseover is the most common event. So I
confidently expect non-traditional user agents to define mouse events, too. This makes rule 1
less important than the other two.
The WebAim site adds some interesting notes.
It advises against using the change event, contrary to what W3C advises.
"When a user tries to scroll the list of options, the JavaScript interprets this scrolling as
an "onSelect" event, which then sends the user to another page. It is nearly impossible to
navigate through such menu systems without a mouse."
Good thinking.
access-board.gov, the official site of the
US Access Board, also has some notes on events. Curious is its insistence that the mousedown
and mouseup events cause confusion. I disagree strongly: the average user doesn't notice the difference.
Since mousedown/up events
generally offer more information
about the event than click, they are by far my preferred events.
As to the change event handler, access-board states that
"it presents tremendous accessibility problems for many commonly used screen readers and should be avoided."
Unfortunately these tremendous problems are not further explained. In my opinion the tremendous
problem is actually selecting an option from a pulldown, and not the event.
Finally, both
park.org and
trace.wisc.edu
recommend "active triggering": you should use events where the user actually does something
(like click or select) not events that occur without the user taking
a conscious decision to do something (like mouseover or load).
Although this is not entirely untrue, I've got serious doubts about the inclusion of
the load event. It
can be argued that this event is an active trigger: the user has
made the conscious decision to go to another page.
JavaScript and accessibility is very much an unexplored area, despite the confidence with which some sites advertise this or that solution which will cause all your problems to disappear.
As a JavaScript developer, you should start bearing accessibility issues in mind. This doesn't mean that you must immediately solve every single issue you find. Some are tough nuts to crack or even unsolvable. Nonetheless you should make an effort, or at least think about the issue, even though your conclusion might be that the script cannot be made accessible.
When you do find a nice solution to a nasty problem, please post it to mailing lists or forums you're a member of. Remember that there are many more developers working on the same problems and that they'll welcome a good idea.
(Please don't send your solutions directly to me. Usually I'm too busy to evaluate them and paste them into this page)
Some useful pages: