Missing skip link
keyboard/skip-link-missing
- WCAG success criterion
- 2.4.1 (level A)
- Outcome class
- Hint only. An automated check that by design reports review hints only: its findings are marked for manual review, never as confirmed violations.
- Area
- Accessibility, Navigation & Operation
- Default severity
- medium
- axe-core rule
skip-link
Why we flag this
Keyboard users must tab through the entire navigation on every page change.
No link with a recognizable 'skip'/'to content' text or anchor to #main/#content at the top of the page.
What the rule checks
Scope. Pages with blocks a keyboard user has to pass to reach the main content: links or other tab stops in front of it. A page without any link or focusable element has nothing to bypass.
Expectation. needs_review once per page (page-level, at the root) when header or navigation links precede the main content and no link bypasses them: no fragment link to the start of the main content, no run of in-page links in front of the first link that leaves the page. A skip link counts in any language, also when it is visually hidden until focused, and also when a script inserts it after load. Review, not violation: 2.4.1 can also be met by landmarks and headings. A page without any link or focusable element is not applicable (nothing to tab past).
Source. WCAG 2.2 SC 2.4.1 Bypass Blocks; techniques G1 (skip link at the top), ARIA11/H69 (landmarks, headings)
Detection: shared; needs dom.
Failing example
The check flags this for review. Corpus case interaction_skip_link_missing. The page may contain further findings for other rules.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Museum shop without a skip link</title>
<style>
body { font-family: sans-serif; margin: 0; padding: 16px; color: #111; background: #fff; }
a, button { display: inline-block; min-width: 44px; min-height: 44px; padding: 12px; box-sizing: border-box; margin: 4px; }
.skip { position: absolute; left: -9999px; }
.skip:focus { left: 16px; }
</style>
</head>
<body>
<!-- needs_review (2.4.1): a header and a navigation repeat on every page,
and no link bypasses them -->
<header>
<p>Example Museum</p>
<a href="/tickets">Tickets</a>
<a href="/members">Members</a>
</header>
<nav aria-label="Main">
<a href="/" aria-current="page">Home</a>
<a href="/visit">Visit</a>
<a href="/shop">Shop</a>
</nav>
<main>
<h1>Museum shop</h1>
<p>Catalogues, posters and postcards.</p>
</main>
<footer><p>Example Museum footer</p></footer>
</body>
</html>Passing example
The check passes here and reports nothing. Corpus case skip_link_language. The page may contain further findings for other rules.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Lien d'évitement en français</title>
<style>
.skip-link { position: absolute; left: -9999px; }
.skip-link:focus { left: 0; }
</style>
</head>
<body>
<!-- #642: a skip link is recognised by its same-page target placed before
the first regular link, not by its (here French) text. -->
<a href="#main" class="skip-link" id="skip">Aller au contenu</a>
<header>
<a href="/">Accueil</a>
</header>
<nav aria-label="Navigation principale">
<ul>
<li><a href="/apprendre/">Apprendre</a></li>
<li><a href="/outils/">Outils</a></li>
</ul>
</nav>
<main id="main">
<h1>L'accessibilité numérique</h1>
<p>Le contenu principal de la page.</p>
</main>
<!-- Same text and target, but after the regular links and outside every
landmark: ordinary content, still reported. -->
<div>
<a href="#main" id="stray-link">Aller au contenu</a>
</div>
<footer>
<p>Pied de page</p>
</footer>
</body>
</html>This page is generated from the rule catalogue and the rule contracts; see therule overview for how the outcome classes are derived.