Without a skip link, a keyboard user visiting a page with a navigation menu of 30 items must press Tab 30 times before reaching the main content — on every single page load. This is not a theoretical concern; it is a documented and cited reason why keyboard users abandon websites. WCAG 2.2 SC 2.4.1 (Bypass Blocks) specifically requires a mechanism to skip repeated blocks of content. Section 508 2018 Refresh 302.1 requires a clear path to primary functionality. The skip link requirement applies regardless of whether your navigation is long or short — it is a baseline expectation for any multi-page site. SPA route transitions that re-render navigation without a skip link create the same problem on every virtual page navigation.
Medium because the missing skip link significantly degrades keyboard navigation efficiency but does not create an absolute barrier — all content remains reachable via Tab.
Add a skip link as the first focusable element in your root layout. It should be hidden by default and visible on focus. In Next.js App Router, edit src/app/layout.tsx:
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<a
href="#main-content"
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-blue-600 focus:text-white focus:rounded"
>
Skip to main content
</a>
<Header />
<main id="main-content">{children}</main>
<Footer />
</body>
</html>
);
}
In plain CSS, if not using Tailwind:
.skip-link {
position: absolute;
top: -100%;
left: 1rem;
z-index: 9999;
}
.skip-link:focus {
top: 1rem;
background: #0066cc;
color: white;
padding: 0.5rem 1rem;
border-radius: 4px;
text-decoration: none;
}
Ensure id="main-content" exists on the <main> element; without it, the anchor href target is broken.
ID: accessibility-basics.keyboard-focus.skip-link
Severity: medium
What to look for: Enumerate every relevant item. Check for a "Skip to Main Content" or similar skip link at the very beginning of the page. It should be visible on focus (hidden by default is acceptable). When activated, focus should move directly to the main content area, bypassing repetitive navigation.
Pass criteria: At least 1 of the following conditions is met. A skip link exists, is visible on Tab from page start, and moves focus to the main content area or <main> element when activated.
Fail criteria: No skip link exists, or the skip link does not move focus to main content.
Skip (N/A) when: Never — skip links benefit all keyboard users.
Detail on fail: "No skip link found on the page. Users must Tab through entire navigation before accessing main content."
Remediation: Add a skip link at the top of your root layout:
export default function RootLayout({ children }) {
return (
<html>
<body>
<a href="#main-content" className="skip-link">
Skip to main content
</a>
<header>{navigation}</header>
<nav>{moreNav}</nav>
<main id="main-content">{children}</main>
<footer>{footer}</footer>
</body>
</html>
);
}
Style the skip link to be hidden by default but visible on focus:
.skip-link {
position: absolute;
left: -9999px;
z-index: 999;
}
.skip-link:focus {
left: 0;
top: 0;
background-color: #0066cc;
color: white;
padding: 1rem;
}