Keyboard and Focus · 2 / 7
lesson 2

Skip links

One link, hidden until focused, that saves keyboard users dozens of tab presses on every page.

~ 11 min read·lesson 2 of 7
0 / 7

Open any news site. Count the links in the top navigation: site logo, search, sign in, every category, every subcategory. Twenty links is normal. Now imagine pressing Tab twenty times every single page, just to reach the article. That's the keyboard-user experience without a skip link.

A skip link is the first link on the page. Press Tab once, and a button appears (usually top-left) that says something like "Skip to main content". Activate it, and focus jumps past the navigation. One key. Done.

It is the single highest-leverage accessibility feature on the web, and it takes maybe ten lines of CSS plus a single anchor tag. There is no excuse.

Why skip links exist

Skip links exist because keyboard navigation is sequential. A mouse user can click the article body directly. A screen-reader user has rotor menus and headings to jump around with. But a sighted keyboard user — someone with a hand injury, an RSI, a tremor, or just a strong preference — has only Tab and Shift+Tab.

Without a way to skip, every page begins with the same procession of header links. Multiply that by every navigation event in a session, and you've made the site ten times slower for them than for a mouse user.

WCAG calls this success criterion 2.4.1, "Bypass Blocks." Most landmark elements (<nav>, <main>, <aside>) help screen readers, but a skip link is the only mechanism that helps a sighted keyboard user too.

Tip

If you remember nothing else from this course: add a skip link. Right now. To everything you ship.

Building one

The recipe has two parts: the link, and the target.

layout.html
<body>
<a href="#main" class="skip-link">Skip to main content</a>

<header>
  <nav>...lots of links...</nav>
</header>

<main id="main" tabindex="-1">
  <h1>Article title</h1>
  <p>...</p>
</main>
</body>

A few things to notice:

  • The skip link is the very first focusable element in the body. It must come before the navigation, or it can't skip past it.
  • The target is <main> with an id="main". The browser scrolls there and moves focus to it.
  • tabindex="-1" on <main> is the trick that makes focus actually move. By default, focus only follows fragment links to elements that are already focusable (links, buttons, inputs). <main> is not focusable on its own. With tabindex="-1", it becomes programmatically focusable, so the skip works in every browser.

Without tabindex="-1", several browsers will scroll to the target but leave focus on the link — so the next Tab press goes back into the navigation you were trying to skip.

The visually-hidden trick

The skip link should be invisible until focused — visible to keyboard users, out of the way for everyone else.

skip-link.css
.skip-link {
position: absolute;
top: 0;
left: 0;
padding: 0.75rem 1rem;
background: #000;
color: #fff;
/* Move it offscreen, but stay focusable */
transform: translateY(-120%);
transition: transform 0.15s;
z-index: 100;
}

.skip-link:focus {
transform: translateY(0);
}

Three rules to live by:

  1. Don't use display: none. That removes it from the tab order entirely, defeating the point.
  2. Don't use visibility: hidden. Same problem.
  3. Do keep it focusable but visually offscreen, then bring it back with :focus or :focus-visible.
Watch out

A common older pattern uses clip: rect(0 0 0 0) or width: 1px; height: 1px; overflow: hidden as a "visually hidden" technique. Those work, but they don't animate, and the link sometimes flashes a tiny dot when focused. The transform approach above is cleaner.

More than one skip link?

For most sites, one skip link is plenty. Long, multi-section pages (a documentation site, a long form, a multi-step checkout) might benefit from two: "Skip to main content" and "Skip to footer," or "Skip to filters" and "Skip to results."

Skip to main content before focusSkip to main content after Tab
Skip-link visibility states. Hidden until tab brings it forward.

If you add multiple, keep them stacked together at the very top, and order them by usefulness (most-skipped-to first).

check your understanding
Why does the skip-link target need tabindex="-1"?

Try it yourself

check your understanding
Where in the HTML must the skip link appear to do its job?
check your understanding
Which CSS technique correctly hides a skip link until it's focused?
check your understanding
The first time a user presses Tab on your site, focus lands on a Search input in the header. What's wrong?
← prevnext lesson →
KeepLearningcertificate
for completing
Keyboard and Focus
0 of 7 read