Highlighting HTML access keys

Sponsored links

Access keys enables users to effectively navigate user interfaces using the keyboard instead of the mouse. This is often faster, especially for experienced users.

Most applications have access keys. But when it comes to websites, you rarely see any.

One reason for this is that even though browsers support access keys, they do not display the key automatically. This makes it cumbersome for web authors to add access keys to their sites.

Access keys may not be that relevant on regular websites, but for application-like sites they are necessary to enable the users to use the site as efficiently as the would use a regular application.

The following script does the dirty work of showing the access keys by underlining the letter like in regular applications. The web author then only has to supply the ACCESSKEY attribute on the relevant HTML elements.

The highlighting is done by underlining the first appearance of the access character. This is done by inserting a SPAN element. For example,

<a href="http://www.google.com" accesskey="g">Google</a>

is changed to

<a href="http://www.google.com" accesskey="g"><span class="accesskey">G</span>oogle</a>.

Now the G is underlined, so that users know that pressing Alt+G (Control+G on Mac) will take them to Google. This is done using DHTML, so you wont actually see this change in your code. The result will look like this:

Google

For input elements, the insertion is done on the belonging LABEL element. In the following example, the Q in "Query" will be highlighted:

<label for="query">Query</label><input type="text" id="query" accesskey="q">

You can specify how the access key is highlighted using CSS. If you want to underline the access key (the standard way of highlighting), you should add the following rule to your style sheet:

span.accesskey { text-decoration: underline; }

If your links are already underlined, access keys for links will not be additionally underlined. Instead you can use a border:

a span.accesskey { border-bottom: 1px solid; }

To activate the highlighting, include the two Javascript functions below and call highlightAccessKeys() when your page has loaded, e.g. in the onload event.

All this is demonstrated in the sample document.

Enjoy!

// Highlighting HTML Access Keys by Christian Schmidt
// This code may be freely used, copied, modified, distributed etc.

// Iterates through all elements that support the ACCESSKEY attribute.
function highlightAccessKeys() {
    //don't do anything in old browsers
    if (!document.getElementsByTagName) return;

    var labels = document.getElementsByTagName('LABEL');
    for (var i = 0; i < labels.length; i++) {
        var control = document.getElementById(labels[i].htmlFor);
        if (control && control.accessKey) {
            highlightAccessKey(labels[i], control.accessKey);
        } else if (labels[i].accessKey) {
            highlightAccessKey(labels[i], labels[i].accessKey);
        }
    }

    var tagNames = new Array('A', 'BUTTON', 'LEGEND');
    for (var j = 0; j < tagNames.length; j++) {
        var elements = document.getElementsByTagName(tagNames[j]);
        for (var i = 0; i < elements.length; i++) {
            if (elements[i].accessKey) {
                highlightAccessKey(elements[i], elements[i].accessKey);
            }
        }
    }
}

// Highlights the specified character in the specified element
function highlightAccessKey(e, accessKey) {
    if (e.hasChildNodes()) {
        var childNode, txt;
        
        //find the first text node that contains the access character
        for (var i = 0; i < e.childNodes.length; i++) {
            txt = e.childNodes[i].nodeValue;
            if (e.childNodes[i].nodeType == 3 &&
                txt.toLowerCase().indexOf(accessKey.toLowerCase()) != -1) {
            
                childNode = e.childNodes[i];
                break;
            }
        }
        
        if (!childNode) {
            //access character was not found
            return;
        }

        var pos = txt.toLowerCase().indexOf(accessKey.toLowerCase());
        var span = document.createElement('SPAN');
        var spanText = document.createTextNode(txt.substr(pos, 1));
        span.className = 'accesskey';
        span.appendChild(spanText);

        //the text before the access key
        var text1 = document.createTextNode(txt.substr(0, pos));
        //the text after the access key
        var text2 = document.createTextNode(txt.substr(pos + 1));
        
        if (text1.length > 0) e.insertBefore(text1, childNode);
        e.insertBefore(span, childNode);
        if (text2.length > 0) e.insertBefore(text2, childNode);

        e.removeChild(childNode);
    }
}