Implementing Skip Links
Implementing Skip Links
Skip links allow keyboard users to bypass repetitive content (like navigation menus) and jump directly to the main content. They're one of the simplest yet most impactful accessibility features you can add to any website.
Why Skip Links Matter
Consider a website with 20 navigation links. Without a skip link, keyboard users must tab through all 20 links on every page before reaching the content. Skip links solve this problem.
WCAG Requirement
WCAG 2.4.1 Bypass Blocks (Level A): Mechanisms must be available to bypass blocks of content repeated on multiple pages.
Skip links are the most common way to meet this requirement.
Basic Skip Link Implementation
<body>
<a href="#main-content" class="skip-link">
Skip to main content
</a>
<header>
<nav>
<!-- Navigation with many links -->
</nav>
</header>
<main id="main-content" tabindex="-1">
<h1>Page Title</h1>
<!-- Main page content -->
</main>
</body>Styling Skip Links
Skip links should be:
- Visually hidden by default
- Visible when focused
- High contrast for visibility
.skip-link {
position: absolute;
top: -100%;
left: 16px;
padding: 12px 16px;
background-color: #000000;
color: #ffffff;
font-weight: 600;
text-decoration: none;
border-radius: 4px;
z-index: 9999;
transition: top 0.2s ease;
}
.skip-link:focus {
top: 16px;
}Tailwind CSS Version
<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-primary
focus:text-primary-foreground
focus:rounded-md
focus:font-medium
"
>
Skip to main content
</a>Multiple Skip Links
For complex pages, provide multiple skip links:
<div class="skip-links">
<a href="#main-content">Skip to main content</a>
<a href="#main-nav">Skip to navigation</a>
<a href="#search">Skip to search</a>
<a href="#footer">Skip to footer</a>
</div>.skip-links {
position: absolute;
top: -100%;
left: 16px;
z-index: 9999;
display: flex;
flex-direction: column;
gap: 8px;
}
.skip-links:focus-within {
top: 16px;
}
.skip-links a {
padding: 12px 16px;
background: #000;
color: #fff;
text-decoration: none;
border-radius: 4px;
}
.skip-links a:focus {
outline: 2px solid #fff;
outline-offset: 2px;
}React Implementation
function SkipLink({ href, children }) {
return (
<a
href={href}
className="skip-link"
>
{children}
</a>
);
}
function Layout({ children }) {
return (
<>
<SkipLink href="#main-content">Skip to main content</SkipLink>
<Header />
<main id="main-content" tabIndex={-1}>
{children}
</main>
<Footer />
</>
);
}Next.js/App Router Implementation
// app/layout.tsx
import './skip-link.css';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<a href="#main-content" className="skip-link">
Skip to main content
</a>
<Header />
<main id="main-content" tabIndex={-1}>
{children}
</main>
<Footer />
</body>
</html>
);
}Important Implementation Details
1. Target Element Must Be Focusable
<!-- The target needs tabindex="-1" to receive focus -->
<main id="main-content" tabindex="-1">
...
</main>Without tabindex="-1", some browsers won't actually move focus to the element.
2. Remove Focus Outline on Target
/* Prevent ugly outline on main when skip link used */
main:focus {
outline: none;
}3. Handle Single-Page Apps
// Reset focus on route change
useEffect(() => {
const mainContent = document.getElementById('main-content');
if (mainContent) {
mainContent.focus();
}
}, [pathname]);Testing Skip Links
- Load the page and press Tab: Skip link should appear
- Press Enter on skip link: Focus moves to main content
- Continue tabbing: Focus should be after navigation
- Screen reader test: Skip link announced correctly
Common Mistakes
Mistake 1: Skip link that doesn't actually skip
<!-- Bad: Just scrolls, doesn't move focus -->
<a href="#main-content" onclick="smoothScroll('#main-content')">Skip</a>
<!-- Good: Focus actually moves -->
<a href="#main-content">Skip to main content</a>
<main id="main-content" tabindex="-1">...</main>Mistake 2: Skip link hidden from screen readers
/* Bad: Hidden from everyone */
.skip-link {
display: none;
}
/* Good: Visually hidden but accessible */
.skip-link {
position: absolute;
top: -100%;
}
.skip-link:focus {
top: 16px;
}Skip Link Checklist
- Skip link is the first focusable element on the page
- Link text clearly describes the action
- Target element has tabindex="-1"
- Link becomes visible on focus
- High contrast colors when visible
- Tested with keyboard navigation
- Tested with screen readers
Was this article helpful?