A Skip Link Primer

Of all the accessibility enhancements that can be made to a page, adding a "skip to content" link is one of the easier wins. These links allow keyboard-only (non-mouse) users to quickly jump to the page's main content or other important sections.

In fact, if you need to conform to WCAG, Level A or above section 2.4.1 requires it.

"A mechanism [...] to bypass blocks of content that are repeated on multiple Web pages."

There's some important nuances to this seemingly simple feature, both in use and implementation, that I'm going to explore.

Important disclaimer: accessibility is hard and there's a lot of techniques and opinions out there. If you think I missed something, please contribute to the conversation in the comments.

Skip link users

To correctly add skip links to your site, it's important to understand who uses them and why. Skip links are an important feature that allows keyboard and screen reader users to skip past repetitive content on a page. Let's break this down.

Keyboard users

At one point in time, skip links were helpful for screen readers, but that is generally no longer the case. Modern screen readers can navigate a page using headings, ARIA roles and links. If your page is marked up with good semantic structure and enhanced with ARIA, a screen reader will be able to get around just fine and will have little use for skip links.

There's a wide variety of sighted people who may be unable to use a mouse or choose to use only a keyboard to navigate a page. These individuals can have disabilities that range from loss of fine motor control to the inability to use, or loss of, a limb. Others may not be able to use a mouse or a keyboard and instead use a switch or "puff and sip" device activated by the mouth.

In all of these cases, pages are navigated using the common keyboard commands: tab, shift + tab, arrows, enter and space.

Repetitive content

Try this experiment: go to a page at amazon.com. Now put your mouse aside and start navigating using the tab key. How many times do you have to hit tab before you can add an item to your cart? (answer: 40) To buy something on another page you'd have to hit tab 40 times again — frustrating!

Skip links allow keyboard users to bypass all that effort so they can quickly get to their task. Screen readers have a means for skipping around a page, but keyboard users don't have special software, so skip links provide a basic version of this functionality.

Implementing skip links

There's nothing fancy about skip links — they're just simple anchor links.

	<a href="#content">Skip to main content</a>
	<!-- presumably some stuff in between -->
	<main id="content" role="main">…</main>

Let's take a look at what's going on here. First, the skip link is the first thing after the opening <body> tag. That's so the link will be the first thing a keyboard user encounters when they start navigating the page. To make it a link that scrolls within the page, the href attribute should start with the pound (#) character followed by the id of the link's destination.

Next, the destination of the link needs to have an id attribute that matches the href of the link (sans # symbol). So if our href="#content", the wrapper needs to have id="content". The text of the id and href can be anything as long as it matches.This is useful if you want to have multiple skip links.

In the past, it was necessary to use named anchors as targets that look like <a name="content"></a>, but ids are now recommended as named anchors now throw a validation warning.

There's just one catch

Some browsers, specifically Chrome (as of version 40) and IE8 & 9, don't move the keyboard's focus from the anchor link after it's clicked. This is a major problem for people who use these browsers because, although the page might scroll to the desired location, focus remains at the anchor link so the next press of the tab key moves the focus to the next thing after the link instead of moving into the desired content.

There's some JavaScript solutions out there that apply a tabindex="-1" to the target container, allowing focus to be given to these elements (but keeping them out of the normal keyboard tab flow). I generally prefer to skip the JavaScript and manually add the tabindex to the element.

<main id="content" role="main" tabindex="-1">

See the Pen dPNMgp by Jeremy Fields (@ten1seven) on CodePen.

This technique is simpler than adding additional JavaScript and does no harm to browsers that already move focus correctly.

But wait, now the container gets a focus outline when it's linked to or clicked within! That's correct, now that this element can receive focus it also gets the default focus styling. Now, I'm a strong advocate of leaving focus styling in place because they're an important indicator of what is currently focused, except in this case.

Why break this important rule? Browsers that have implemented anchor links correctly will scroll the page to the anchor's destination and implicitly  move focus (no visual indication), allowing keyboard navigation to pick up from the new location. To fix the buggy implementation in some browsers, we have to explicitly move focus to the anchor's destination. Since a visual indication of this focus is not the expected behavior it's safe to remove the focus style.

See the Pen wBgGYm by Jeremy Fields (@ten1seven) on CodePen.

Enhancing with JavaScript

Having the visual focus outline when skipping to a container can be a nice visual enhancement that we wouldn't want mouse users to encounter. Using JavaScript, we can add the tabindex to the target only when a skip link is clicked, making it focusable and allowing the default focus style to show only when a skip link is used.

See the Pen XJpdPv by Jeremy Fields (@ten1seven) on CodePen.

An even better version would be to combine the JavaScript and non-JavaScript techniques for better progressive enhancement.

See the Pen PwWNxO by Jeremy Fields (@ten1seven) on CodePen.

Link to the container or content?

The link target can be any HTML element. Some developers choose to link to the content container, others link to the content's heading and others still use an empty named anchor at the top of the content.

All of these methods work and are valid, but I prefer to link to the container because it uses less markup and doesn't depend on the content having a specific structure.

How many skip links?

Skip links are so useful that it can be valuable to link to several sections of a page and even from within the page to other sections. This can provide keyboard users similar functionality to a screen reader's ability to jump between sections. When adding multiple skip links, keep in mind that their goal is to reduce repetitive lists of links. If the skip link list itself becomes too long, a "skip the skip links" link might be required (and might indicate that there's too many skip links).

If you need a longer list of skip links for your site, I really like the SkipTo plugin from the PayPal Accessibility Team. Their solution was to create a toggle-able list of links that users can easily bypass without opening. If that wasn't elegantly simple enough, their script crawls the page and looks for ARIA roles and headings and automatically turns them into a list of skip links.

This is a great solution but may be overkill for many pages so I recommend only considering it if the extra functionality is worth the additional code on your site.

Designing skip links

Skip links don't need to be intrusive. In fact, it's really easy to add them with no impact on the page's design. 

The most elegant technique is to move the links off page using CSS positioning, then move them into view when they receive focus. This makes them very lightweight with no JavaScript dependency.

Example of hidden skip link displaying on :focus.

Wrapping it up

Finally, here's an example of all the techniques working together.

See the Pen KwaMwY by Jeremy Fields (@ten1seven) on CodePen.

Do you have any questions or comments? Keep the conversation going in the comments.

Further Reading

WebAIM "Skip Navigation" Links

Jeremy leads Viget's front-end development team, and has helped make accessibility part of every site we build. Based in our Boulder, CO, office, Jeremy has worked with clients like Time Life, PUMA, and Dick's Sporting Goods.

More posts by Jeremy