Skip to the Main Content

Note:These pages make extensive use of the latest XHTML and CSS Standards. They ought to look great in any standards-compliant modern browser. Unfortunately, they will probably look horrible in older browsers, like Netscape 4.x and IE 4.x. Moreover, many posts use MathML, which is, currently only supported in Mozilla. My best suggestion (and you will thank me when surfing an ever-increasing number of sites on the web which have been crafted to use the new standards) is to upgrade to the latest version of your browser. If that's not possible, consider moving to the Standards-compliant and open-source Mozilla browser.

January 8, 2006

Editable Accesskeys

Accesskeys are a very nice mechanism for making your website more accessible. You can define a set of keyboard shortcuts for common navigational tasks, making it easier for visitors, who can’t (or don’t wish to) use a mouse, to find their way around your site. For instance, on this site, hitting Alt -4 (Cntrl -4 on a Mac) takes you to the search form on the current page; Alt -1 (Cntrl -1) takes you to the main page of this blog, etc.

Unfortunately, accesskeys suffer from two big drawbacks

  1. There’s no easy way for visitors to discover what accesskeys are defined on a particular site.
  2. The accesskeys you define may conflict with the user’s existing keyboard shortcuts. Even if they don’t, accesskey assignments vary from site to site, so there’s no “muscle memory” advantage to them.

The first problem is easy to fix. Long ago, I put a listing of the accesskeys, defined here, in the footer of each page. Scroll down to take a look at it. The markup that generated the footer is

<div id="footer">   
<h2>Access Keys:</h2>
<dl id="AccessKeyList"> <dt>0</dt><dd><a href="/~distler/blog/accessibility.html" accesskey="0">Accessibility Statement</a></dd> <dt>1</dt><dd>Main Page</dd> <dt>2</dt><dd>Skip to Content</dd> <dt>3</dt><dd>List of Posts</dd> <dt>4</dt><dd>Search</dd> <dt>p</dt><dd>Previous (individual/monthly archive page)</dd> <dt>n</dt><dd>Next (individual/monthly archive page)</dd> </dl>
<a href="/~distler/blog/archives.html" accesskey="3"></a> </div>

and it can be included at the bottom of every page, using SSI, PHP or, in my case MovableType’s <MTInclude> directive. Of course, this definition-list didn’t have to be in the footer of the page. It could have been in a CSS drop-down menu at the top of the page or … The point is to make it unobtrusive, and yet easily-discoverable. Someone, with better design skills than I, could have found a more artful solution.

The second drawback seemed harder to surmount. Somehow, we need to let the user customize the accesskey assignments. But how?

Recently, Gez Lemon found a solution using server-side scripting. Unfortunately, it was more than a little cumbersome. As a web-author, it requires mucking with the markup of your pages1. As a user, it involves thoroughly unnecessary back-and-forth interaction with the server. Still, it was inspirational. Once you realize it can be done, you start to think about other ways to achieve the same effect.

I wanted something that would not involve mucking with the existing markup of my pages, and which would work client-side (so as to be as fast and smooth as possible). If you’ve read this far, you probably want to see it in action. Scroll down2 to the bottom of the page and hit the, hitherto mysterious, edit button. You can assign any keyboard character you want to an accesskey, though most browsers do not distinguish between uppercase and lowercase letters. If you want to disable one (or all) of the accesskeys, simply delete the corresponding character. When you’re happy, hit save. You can now use your new accesskey assignments anywhere on this blog. And they’ve been saved in a cookie, for your future surfing pleasure. If, instead, the current accesskey assignments suit you, just hit reset.

No markup was butchered to achieve this effect. All I needed to do was include this Javascript file and add initializeAccessKeys(); to the onload-handler for my pages. In fact, the Javascript uses the existing markup (a definition-list whose id="AccessKeyList")3 as an editing template for customizing the accesskeys.

I rather enjoyed crafting this, my first somewhat nontrivial bit of Javascript programming. There’s something delightfully recursive about using DOM-scripting to add event-handler attributes which, when activated, trigger other DOM-scripting operations.

I’ve only tested it in a few browsers (Mozilla, Safari and Opera), but expect it to work in others as well. Suggestions for improvements are welcome.

Update (1/16/2006):

Gez Lemon has crafted a Greasemonkey script to obtain similar (but not quite as good) functionality on any website with accesskeys. I’ve written a followup post about it. I’ve also revised my Javascript to play more nicely with Gez’s script.

Update (4/2/2006):

Rich Pedley wins the prize for catching a bug in the previous version of this Javascript. I’ve updated it to fix the bug.

Postscript: Event Handlers

Getting keyboard navigation to work right in the presence of certain event-handlers seems to be a black art. All the sources I’ve looked at give incorrect advice. As a consequence, I, myself, have been doing it wrong for years now.

onclick="..."

by itself doesn’t work right. The user should be able to trigger this handler by hitting Return. But that doesn’t happen in Safari (and, perhaps, other browsers).

onclick="..."
onkeypress="..."

will cause the handler to be triggered by hitting any key. Which is not what you want: that breaks Tab-navigation. What does work is

onclick="..."
onkeypress="if(window.event.keyCode == 13){...; return false;}"

Since I haven’t seen this explained anywhere4, I figured I’d spell it out here, and save someone else from tearing their hair out, too.


1 Among other drawbacks, Gez’s implementation is limited to the creation of <a href="" accesskey=""> and <label for="" accesskey=""> elements. No other attributes are allowed, and you can’t use it with <area>, <button>, <input>, <legend> or <textarea>, all of which are permitted to carry accesskey attributes.

2 You can also use keyboard navigation: hit Shift -Tab, to move to the bottom of the page, highlighting the edit button. You should be able to hit return to activate editing of the accesskeys for this site (you can navigate between the editing field using Tab and Shift -Tab).

3 The script assumes a <dl id="AccessKeyList">. If you want to give the definition-list containing the accesskeys and their meanings a different id, change the value of the accesskeylistid variable in the script.

4 Peter-Paul Koch’s otherwise-excellent table of Javascript Event support is, I’m afraid, incorrect on the status of onclick support in Safari.

Posted by distler at January 8, 2006 11:54 PM

TrackBack URL for this Entry:   http://golem.ph.utexas.edu/cgi-bin/MT-3.0/dxy-tb.fcgi/723

13 Comments & 4 Trackbacks

Re: Editable Accesskeys

Very interesting, the edit/save function is a nice feature. But is DOM scripting the right approach when it comes to Accessibility?

For this solution to degrade nicely, I think no accesskeys should be set by default, so if the script fails, the user is not stuck with your own values.

For people interested in Server-Side solutions, this is another approach.

Posted by: Thierry on January 15, 2006 11:21 AM | Permalink | Reply to this

Client vs. Server

But is DOM scripting the right approach when it comes to Accessibility?

I certainly don’t think they are, in any way, antithetical. To the contrary, there are lots of ways in which judicious use of Javascript can enhance accessibility.

For this solution to degrade nicely, I think no accesskeys should be set by default, so if the script fails, the user is not stuck with your own values.

Well it does degrade to the first important function: making the accesskeys discoverable.

Once users knows that a particular accesskey conflicts with their pre-existing keyboard shortcut, they can always hit ALT and then the desired key to activate their keyboard shortcut (a Windoze-centric workaround; on the Mac, I’m not aware of any conflicts, because keyboard shortcuts all use ⌘-X, perhaps with some further modifier, like ⌘-option-X, and so don’t conflict with accesskeys which use Cntrl-X).

That’s not ideal. But it’s better than what exists on most websites, where the user doesn’t even know that the site-owner has defined an accesskey that conflicts with his keyboard shortcut until he tries to use that shortcut.

I really disagree that website should avoid defining a default keybinding for their accesskeys. As long as those keybindings are discoverable and modifiable by the user, there’s positive benefit to having some well-chosen defaults in place.

I like the fact that the server-side solutions (yours and Gez’s) work even with Javascript off. That’s traded off against the arguable greater ease-of-use of the client-side solution I am proposing.

Posted by: Jacques Distler on January 15, 2006 12:01 PM | Permalink | PGP Sig | Reply to this

Scripting

I wrote:

To the contrary, there are lots of ways in which judicious use of Javascript can enhance accessibility.

One great example is Gez Lemon’s Greasemonkey script to add some approximation of the above functionality to any site which uses accesskeys. See my followup post for more thoughts on this.

Posted by: Jacques Distler on January 15, 2006 4:50 PM | Permalink | PGP Sig | Reply to this

Re: Scripting

What I meant is that there is no Accessibility enhancement if a script does not degrade nicely.
For example, I would have no problem with your technique if you were using the DOM to set the default Accesskeys. If the idea is to address conflicting Accesskeys issues then I think the technique should make sure such things do not happen.

Posted by: Thierry Koblentz on January 16, 2006 2:41 PM | Permalink | Reply to this

Discoverability is an enhancement

What I meant is that there is no Accessibility enhancement if a script does not degrade nicely.

Yes, there is.

Not being surprised when one presses Alt-X, expecting a certain keyboard shortcut to be executed, and having something else happen instead, counts as an Accessibility enhancement in my book.

Informing the user that they need to press Alt, then X to get the desired keyboard shortcut, whereas Alt-X triggers an accesskey does enhance what they can do from the keyboard.

It is, however, less convenient that allowing them to retain their familiar keyboard shortcut, and remap the accesskey to some other keybinding.

The latter requires Javascript.

There’s another advantage to my approach: at least in its latest version, it coexists nicely with Gez Lemon’s Greasemonkey script, whereas none of the server-side implementations do.

Posted by: Jacques Distler on January 16, 2006 3:41 PM | Permalink | PGP Sig | Reply to this

Re: Discoverability is an enhancement

Not being surprised when one presses Alt-X, expecting a certain keyboard shortcut to be executed, and having something else happen instead, counts as an Accessibility enhancement in my book.

I think you’re missing my point. As long as the default Accesskeys can be changed by the user everything is fine, but without script support you’re “hijacking” his shortcut keys for good.

Why not using the script to plug the accesskey attribute? That way, if there is no script support no keys are set…

Posted by: Thierry Koblentz on January 16, 2006 4:49 PM | Permalink | Reply to this

Re: Discoverability is an enhancement

… but without script support you’re “hijacking” his shortcut keys for good.

I’ll say it again.

His keyboard shortcuts are still there. They’ve just been remapped from ‘Alt-X’ to ‘Alt then X’. A serious problem arises when he doesn’t know that his keyboard shortcuts have been remapped.

That’s something we can easily fix, with or without Javascript.

(Note that the above issue does not arise in Opera or in Macintosh browsers, because the default accesskey keybindings do not conflict with existing keyboard shortcuts there.)

Why not using the script to plug the accesskey attribute? That way, if there is no script support no keys are set…

Because I happen to think that having some default keybindings in place improves the usability for most accesskey-users most of the time.

Rather than having to go through the trouble of supplying keybindings for all the accesskeys before being able to use them (a problem for, say, mobility-impaired users), users need only edit the ones which pose conflicts for them. (And, as I’ve explained, even that is more of a convenience than a necessity.)

Besides, if I did what you said, there would be no keybindings, and no way to set them, if Javascript was turned off. That’s demonstrably worse for all users.

Posted by: Jacques Distler on January 16, 2006 5:16 PM | Permalink | PGP Sig | Reply to this

class=”keyboard”?

That’s completely offtoppic, but just had to mention…

This page has a lot of key-names inside text - all nicely formatted, but I’m wondering why do you use <span class="keyboard">Alt</span> instead of just writing <kbd>Alt</kbd> ?

Posted by: Rene Saarsoo on January 16, 2006 3:57 AM | Permalink | Reply to this

Re: class=”keyboard”?

<kbd>
Indicates text to be entered by the user.
<span class="keyboard">
Indicates (at least, on this site) an individual key pressed on the keyboard.

Not the same thing at all.

Posted by: Jacques Distler on January 16, 2006 7:37 AM | Permalink | PGP Sig | Reply to this
Read the post Greasemonkey Exposes Access Keys
Weblog: blogZero
Excerpt: Following up on a concept by Jacques Distler, Gez Lemon has posted an article and an amazing little Greasemonkey script that not only exposes any accesskeys that are used by a Web site, it also allows you to edit them the suit your preferences. Greasem
Tracked: January 16, 2006 11:52 PM
Read the post Giving the user control over accesskeys
Weblog: 456 Berea Street
Excerpt: The accesskey attribute may cause conflicts with existing shortcut keys. Here are two different approaches to letting users define their own accesskeys.
Tracked: January 27, 2006 5:50 AM

Re: Editable Accesskeys

Hi,

I could be wrong, but I think there is a small bug in your javascript.

If you interchange 2 access keys, then they don’t actually change until the page is refreshed, or you go to a different page.

In my testing I used your page, and interchanged the access keys for the home page and the accessibility statement.

Until recently I thought I wasn’t going to be able to use your javascript, which i want to use along side some other scripts i am adapting.

I hope this small ‘bug’ can be ironed out! (if indeed it is one!)

In case it makes a difference, I am using Firefox 1.5

Posted by: Rich Pedley on April 2, 2006 9:49 AM | Permalink | Reply to this

Bug?

Hmmm…

Very strange. Works for me.

A stale cookie can cause problems (the key-mappings are stored in a cookie). But that is presumably not your problem here.

Can you reproduce the problem from a “fresh” state (i.e., cookie deleted, page reloaded, then attempt to edit the accesskeys)? Or does it only happen after having previously edited the accesskeys?

Posted by: Jacques Distler on April 2, 2006 10:20 AM | Permalink | PGP Sig | Reply to this

Bug?

Just to be clear, none of your edits take effect until you click on “save”. I presume that’s not your problem.

Posted by: Jacques Distler on April 2, 2006 11:30 AM | Permalink | PGP Sig | Reply to this

Re: Bug?

Took a bit of time to test, but I edited the accesskeys on the accessibility statement page - swapping the values for that and the Main Page.

If you then change them back, the problem occurs.

Yes I’ve tried afresh, and yes I clicked save.

Posted by: Rich Pedley on April 2, 2006 1:36 PM | Permalink | Reply to this
Read the post New AccessKeys.js
Weblog: Musings
Excerpt: A new version of Accesskeys.js fixes a bug and an incompatibility with IE/6.
Tracked: April 3, 2006 1:42 AM
Read the post DeThreaded Comments
Weblog: Musings
Excerpt: A Javascript solution for dethreading comments.
Tracked: May 2, 2007 4:11 PM

Post a New Comment