Sticky headers and keyboard accessibility

I recently ran into an issue while navigation via keyboard on an interface with a sticky header/navigation bar. Since the sticky navigation bar is always in view, and since it’s usually higher in the markup than the content, it always receives the first focus despite attempts to focus on content that I’ve skipped to.

In my test environment I created a page with a bunch of content, a sticky navigation bar (Twitter’s Bootstrap 2 framework), and a “skip to content” link which was hidden until focused. Using the keyboard only, when I clicked the “skip to content” link the page did in fact jump to the content area as expected, but when tabbing again – expecting to enter the content area, the focus went to the sticky navigation bar rendering the “skip to content” link useless.

Going through my horde of bookmarks related to accessibility to see if anyone else has experienced this (“Surely it’s common!” I thought), I stumbled upon WebAIM’s website, which has a very solid method of achieving what I’d like to do.

The method is actually really simple and it involves a little semantic markup (of course) and a little JavaScript.

First, to account for Internet Explorer’s wonkiness, you’ll have to set the container IDs you may target to a -1 tabindex, like so:

$('#maincontent').attr('tabindex', '-1');

This will allow the container to accept focus.

So, assuming you’ve given your main content container an ID of #maincontent, we can use the following code to perform the focus actions:

// If we're loading the page with an anchor already set
if (document.location.hash) {
	var myAnchor = document.location.hash;
        // Do anything else with the focused container here, such as a highlight-fade
        setTimeout(function() {
		$(myAnchor).focus();
	}, 100);
}

// If we're clicking on a page anchor (such as our jump links)
$("a[href^='#']").click(function(event) {
	var clickAnchor = "#" + this.href.split('#')[1];
        // Do anything else with the focused container here, such as a highlight-fade
	setTimeout(function() {
		$(clickAnchor).focus();
	}, 100);
});

Inspiration comes from WebAIM. I am working on a more flexible, “object-oriented” method to contribute to our custom framework. I will post these findings in a future post.

View an example of the problem
View an example of the solution