Implement a Skip Link for Navigation-Heavy Sites

TL;DR #

If your pages contain many links or elements before the main content, consider adding a link to the very beginning of the page to help keyboard-navigating users jump directly to the content they care about.

<body>
<header>
<a href="#main-content">Skip to Content</a>

<!-- Potentially cumbersome navigation -->
</header>

<main id="main-content" tabindex="-1">
<!-- Page content -->
</main>
</body>

You can see a skip link at work on this very page—start at the beginning of the page and hit Tab!

Introduction #

When a keyboard user tabs through your page, it's very linear. They start at the very beginning of your page, and tab through each interactive element (buttons, links, and form fields) until they get to the part of the page they want. If there aren't many elements between the top of the page and the content they're looking for, that's fine. But what if there are many contents in the way?

Consider this article on the MDN Web Docs:

MDN documentation for the anchor element. The page header contains the MDN Web Docs logo, three menu dropdown buttons, a searchbar, and a sign-in link. The article is preceded by breadcrumbs, language selection, and a table of contents with eight items.

To get to the main content of the article, you have to first tab through the site logo/homepage link, three navigation menu buttons, a searchbar, a sign-in link, each link in the breadcrumbs, the language selection dropdown and button, and every item in the table of contents. By my count, that's 19 tabs before you reach the article. What's more, if a keyboard navigator follows a link to another page in the docs, they'll have to go through those tabs all over again.

It's repetitive, duplicated, superfluous, and repetitive.

We can help keyboard navigators skip over the repetitive elements at the beginning of every page by implementing skip links. A skip link is an anchor tag placed at the beginning of the page that, when clicked, moves the user's focus to the main contents of the page, skipping over the header and navigation items.

Let's give it a shot.

Skip link setup requires two pieces:

  1. The target element to skip to.
  2. The link itself.

Part 1: The Target #

First, let's identify your target element. This element should contain the main contents of the page that your user would care most about. On many sites, this would be your <main> tag.

Give your target an id. I tend to use #main-content, but I've also seen #main, #contents, and others. It's up to you — pick something you find short and descriptive.

Next, give your target tabindex="-1". When a user follows our skip link, we want their keyboard focus to move to our target. Modern browsers will move that focus for us, but some older browsers will only move the focus if the target is focusable. If it's not focusable, the page will scroll down but the user's focus will still be at the top of the page.

With our id and tabindex in place, our target is good to go:

<main id="main-content" tabindex="-1">
<!-- Page content -->
</main>

Next up, the skip link itself. This should be an anchor tag that links to your target's id — something like:

<a href="#main-content">
Skip to Content
</a>

Crucially, place this link at the very beginning of your page, before other focusable elements. This will make sure your skip link is as discoverable (and useful!) as possible.

As for the link text, pick something descriptive like "Skip to content," "Skip to main content," or "Skip navigation." I tend to go with "Skip to content," since I think it's the most concise of the bunch.

Congrats! You have a skip link now. Test it out on multiple browsers to make sure you're getting both the scroll and focus behavior you'd expect!

Some sites have several important page regions that users may want to skip to, such as a searchbar, or a footer with many important links. It's totally fine to set up multiple skip links. Just don't go overboard — otherwise, your skip links will become part of the same clutter you're trying to avoid.

Many web developers who implement skip links opt to hide the skip link, so it doesn't clutter the page for those who don't need it. This is fine, so long as you make the link visible on focus. When a user tabs to the skip link, it should display prominently, so sighted keyboard users don't miss it.

Using display: none or visibility: hidden will prevent screenreader users from using your skip link, so instead, we'll borrow the styles from this .visually-hidden utility class.

Our styles will look like this:

[href="#main-content"] {
/* Your own prominent styles! */
}

/* Hide skip link when it's not focused */
[href="#main-content"]:not(:focus) {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}

(Or, if you prefer, you could add a .skip-link class to your link and select that in your styles instead!)

Recap #

Skip links let keyboard users skip over the navigation elements that are present on each of your pages, helping them get to the content they were looking for faster. They may be hidden initially, but must become visible when focused.

The skip link's target should contain the main, relevant contents, and as little of the surrounding elements as possible. In addition to the id targeted by the skip link, targets should be made focusable with tabindex="-1", so that the keyboard user's focus picks up at the beginning of the main content.

Further Resources #