What is Skip link?
Skip link: A skip link is a hidden link at the top of a page that appears on keyboard focus and jumps straight to the main content, bypassing the header and navigation.
A skip link is the first focusable element on a page. It is invisible until a keyboard user presses Tab, at which point it appears, usually as a small button at the top left, reading "Skip to main content". Activating it moves focus past the logo, the navigation, the search box and whatever else repeats on every page, straight to the content. Without it, someone using a keyboard or a switch device has to Tab through the same thirty links on every page before reaching anything new. WCAG success criterion 2.4.1, Bypass Blocks, is usually satisfied with exactly this element.
How it should behave
- First in the DOM, before the header, so it is the first Tab stop. Position it visually with CSS if the design wants it elsewhere.
- Visible on focus. Hide it with the visually hidden pattern, never with
display: none, which removes it from the Tab order; on:focusundo the hiding and show it with strong contrast on top of everything. - A working target. The link points at
#main, and themainelement has thatid. Give the targettabIndex={-1}so every browser moves focus there, not only the scroll position, and remove its focus outline since it is not interactive. - More than one on complex apps: skip to navigation, skip to search, skip to results. Keep the list to two or three.
- Visible in the layout when the audience benefits, as on government and documentation sites. A visible skip link is not a failure.
Single-page apps
In a client-rendered app the page does not reload between routes, so the skip link alone does not restore focus order. After a route change, move focus to the new page's heading or to the main element, and update the document title, so keyboard and screen reader users know they have arrived. The skip link then works as it would on a fresh load. Fixed headers that overlap the target need scroll-margin-top on the main element so the content is not hidden under them after the jump.
How to build one in React
MiniDev's SkipLink is a visually hidden anchor that becomes a fixed, raised button on focus. Place it first in the root layout and give main the matching id:
import * as React from "react"
import { SkipLink } from "@/components/ui/skip-link"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<SkipLink href="#main" />
<header>{/* logo, nav, search */}</header>
<main id="main" tabIndex={-1} className="outline-none scroll-mt-16">
{children}
</main>
</body>
</html>
)
}
Put it above the AppShell, so it skips the Topbar and Sidebar it contains. Test it by loading a page and pressing Tab once: the link should appear, and Enter should move focus into the content. Keep a focus-visible ring on any heading you move focus to, so the jump is visible as well as audible. More landmarks and navigation pieces are in the navigation category.
Skip LinkuiSkip to content link that stays visually hidden until focused, then appears fixed in the top corner so keyboard users can jump past navigation in any React app.npx shadcn@latest add @minidev/skip-linkApp ShelluiTailwind app shell layout with a fixed width sidebar slot, a topbar slot and a scrolling main area. The sidebar hides below the md breakpoint for mobile.npx shadcn@latest add @minidev/app-shell