Skip Navigation Implementation for Accessibility
Skip Navigation ("Skip to content") is a link at the top of the page allowing screen reader and keyboard navigation users to skip repetitive navigation blocks and go directly to main content. WCAG SC 2.4.1 (Level A) — a mandatory requirement.
Basic Implementation
<!DOCTYPE html>
<html>
<head>
<style>
.skip-link {
position: absolute;
top: -100px;
left: 0;
padding: 8px 16px;
background: #000;
color: #fff;
font-weight: bold;
z-index: 9999;
text-decoration: none;
transition: top 0.1s;
}
.skip-link:focus {
top: 0;
}
</style>
</head>
<body>
<!-- First element on the page -->
<a href="#main-content" class="skip-link">Skip to content</a>
<header>
<nav><!-- navigation --></nav>
</header>
<main id="main-content" tabindex="-1">
<!-- Main content -->
</main>
</body>
</html>
tabindex="-1" on <main> is necessary — <main> doesn't accept focus by default, and the link should move focus there.
Multiple Skip Links
On complex pages, add multiple links:
<nav class="skip-links" aria-label="Quick navigation">
<a href="#main-content" class="skip-link">Skip to content</a>
<a href="#main-nav" class="skip-link">Skip to navigation</a>
<a href="#search" class="skip-link">Skip to search</a>
</nav>
React Component
function SkipNavigation() {
return (
<nav aria-label="Quick navigation">
<a
href="#main-content"
className="skip-nav-link"
>
Skip to content
</a>
</nav>
);
}
// In App.tsx
function App() {
return (
<>
<SkipNavigation />
<Header />
<main id="main-content" tabIndex={-1}>
<Routes />
</main>
<Footer />
</>
);
}
/* Tailwind */
.skip-nav-link {
@apply absolute -top-full left-0 z-50 px-4 py-2
bg-black text-white font-bold
focus:top-0 transition-all;
}
SPA: Reset Focus on Navigation
In SPAs, the "Skip to content" link works only once. When navigating between pages, focus must be programmatically moved:
function usePageFocusReset() {
const location = useLocation();
const mainRef = useRef<HTMLElement>(null);
useEffect(() => {
mainRef.current?.focus();
// Optional: scroll to top
window.scrollTo(0, 0);
}, [location.pathname]);
return mainRef;
}
function Layout() {
const mainRef = usePageFocusReset();
return (
<>
<SkipNavigation />
<Header />
<main id="main-content" tabIndex={-1} ref={mainRef}>
<Outlet />
</main>
</>
);
}
Timeline
1–2 hours including CSS styles and keyboard testing.







