TJKDesign: Home Page

ez-css Putting the 'less' in table-less layouts. css-101 logo
Bookmark this article at these sites:

A "DOM menu" that is Keyboard "friendly".

It is easier for keyboard users to navigate through long nested lists (mainly navigation menus) when these are "hidden" through the use of "display:none"; but unfortunately for these users, most web designers/developers choose other techniques to make sure all links are exposed to search engines and assistive devices. For this reason, such lists are often "painful" for keyboard users to navigate.

So what this script does is that it creates "skip links" to let users skip entire nested lists (in visual browsers these links do not appear unless users use tabbing navigation).

This solution is based on a Definition List that includes Unordered Lists. It does not need any hooks besides an ID for the menu (the DL). This is what it'll do for you:

  • If there is script support, it writes two stylesheets containing rules to collapse all the DDs with their UL.
  • It wraps the text found inside the DTs into A elements.
  • It "injects" a second anchor (the skip link) in the DTs.
  • The text of this skip link is composed of the string "Skip to:" followed - on the next line - by the text of the next DT in the sequence.
  • It creates and places an anchor past the last link in the menu. It is to be used as a shortcut to jump back to the top of the menu.
  • It "plugs" attributes in these two anchors to create the "skip links" mechanism.
  • It adds the necessary event handlers - where needed - to hide/reveal the DDs.
  • It applies a class to the DTs, the DDs and the skip links.

The markup looks like this:
(borrowed from SeatGuru.com)

<dl id="TJK_SlideMenu" title="Navigation Menu">
	<dt>Airlines: A-B</dt>
	<dd>
		<ul>
			<li><a href="javascript:;">Air Canada</a></li>
			<li><a href="javascript:;">Air France</a></li>
			<li><a href="javascript:;">AirTran</a></li>
			<li><a href="javascript:;">Alaska/Horizon</a></li>
			<li><a href="javascript:;">America West</a></li>
			<li><a href="javascript:;">ATA</a></li>
			<li><a href="javascript:;">British Airways</a></li>
		</ul>
	</dd>
<dt>Airlines: C-F</dt>
	<dd>
		<ul>
			<li><a href="javascript:;">Cathay Pacific</a></li>
			<li><a href="javascript:;">Continental</a></li>
			<li><a href="javascript:;">Delta/Song</a></li>
			<li><a href="javascript:;">Frontier</a></li>
		</ul>
	</dd>
[...]
</dl>

This is the working keyboard friendly menu.

Issues I am aware of:

  • I am using "display:none" with IE5 Mac, so the menu is keyboard friendly, but nested links are not as accessible as they are in other browsers.
  • Safari seems to ignore onkeypress, so skip links appear to keyboard users but are useless.
  • A big one I just found out: using skip links feeds the history object which means keyboard users will have to "paddle back" using the backspace key to reach the document previously visited (make sure to consider this issue before implementing this solution).
    I took care of this issue. I do not use the href value to reach the anchors anymore.

This script should degrade nicely in JS-challenged UAs.

Other "DOM menus" I am aware of: