Tutorial
How to build a skip link
In short
A skip link is the first focusable link on the page and points, via an anchor, to the main content's id. Do not hide it with display:none (that makes it unfocusable); move it off-screen and reveal it on :focus. The target needs an id and tabindex="-1" so focus actually lands there.
At a glance
Put the skip link first
Make the first element in <body> a link with href="#main-content".
Mark the target
Give the <main> id="main-content" and tabindex="-1".
Reveal on focus
Hide the link visually (not with display:none) and reveal it on :focus.
Test
Load the page, press Tab once: the skip link must appear and work.
Every page repeats the same blocks before the real content: logo, main navigation, often a search. Keyboard and screen-reader users would have to tab through all of it on every sub-page. A skip link jumps past those blocks with one keystroke: it is the simplest way to satisfy 2.4.1 (Bypass Blocks).
The problem
<body>
<!-- Kein Skip-Link: Tastaturnutzer muessen sich durch die ganze
Navigation tabben, auf jeder Seite neu -->
<header>
<nav><!-- 30 Menuepunkte --></nav>
</header>
<main>
<!-- Inhalt -->
</main>
</body>
/* Oder: ein Skip-Link, der per display:none unfokussierbar ist */
.skip-link { display: none; }Two variants fail: no skip link at all, or a skip link with display:none. display:none removes the element from the tab order, so it can never receive focus and is useless.
The fix
The link is the first focusable element in the body and points to the main content's id. It only becomes visible on focus.
<body>
<a class="skip-link" href="#main-content">Zum Inhalt springen</a>
<header>
<nav><!-- 30 Menuepunkte --></nav>
</header>
<!-- tabindex="-1" macht das Ziel per Skript/Anker fokussierbar,
ohne es in die Tab-Reihenfolge aufzunehmen -->
<main id="main-content" tabindex="-1">
<!-- Inhalt -->
</main>
</body>/* Sichtbar erst bei Fokus: aus dem Blickfeld geschoben,
aber im DOM und in der Tab-Reihenfolge (nicht display:none!) */
.skip-link {
position: absolute;
left: -9999px;
top: 0;
padding: 0.75rem 1rem;
background: #1d4ed8;
color: #ffffff;
}
.skip-link:focus {
left: 0.5rem;
top: 0.5rem;
z-index: 1000;
}Details often missed
- Do not use left: -9999px alone if the link must support RTL languages: prefer the clip-path or sr-only technique there. For LTR the shown variant is robust.
- The skip link must have real contrast once visible (1.4.3): white text on blue meets that.
- A single skip link to the main content satisfies 2.4.1. On very complex pages you may offer more (e.g. "Skip to search").
Test
- Reload the page and press Tab exactly once.
- The skip link must appear (not stay hidden).
- Press Enter: focus must jump into the main content, not just the scroll position.
Related WCAG criteria
Frequently asked questions
- Why not just display:none for the skip link?
- display:none and visibility:hidden remove the element from the tab order. The link can then never receive focus and is ineffective. Use a visual hiding technique that keeps the element in the DOM and focusable.
- Does the target really need tabindex="-1"?
- Yes, in practice. Without tabindex some browsers move only the scroll, not keyboard focus. tabindex="-1" makes the target focusable via script/anchor without adding it to the normal tab order.
- Where should the skip link jump to?
- To the start of the main content, usually the <main> element with an id like main-content. That skips the header and navigation.
Request a free scan
Tell us your domain — we run a free initial scan and show you the most important barriers.