Accessibility
The skip link: the first link on the page
A skip link is the first focusable element: it sends the keyboard to the main content and skips the menu. WCAG 2.4.1 Bypass Blocks, level A, requires it.
Key points
- Criterion 2.4.1 Bypass Blocks, level A, requires a way to skip repeated blocks of content.
- The skip link is the first focusable element in the body and points at a main with tabindex="-1".
- Hide it with positioning, never with display:none, and let it reappear on focus.
A skip link is a hidden link that appears on the first Tab press and sends focus to the main content, past the navigation repeated on every page. WCAG 2.4.1 Bypass Blocks, level A, asks for exactly that: a mechanism to skip repeated blocks of content.
Where it goes
In the DOM it is the first focusable element: before the header, not after it. It points at the id of the main content, and the target carries tabindex="-1". Without that attribute some browsers only scroll, and the next Tab starts again from the menu. The pattern is described in the WAI-ARIA Authoring Practices, published by the W3C under the W3C Document License.
The minimum markup
Skip to main content
...
...
Three details decide whether it works. The label says where the link goes, not “skip”. The link stays in the document flow, so do not wrap it in a container with aria-hidden. The target has tabindex="-1" so it can take focus, and it must not be hidden with display:none.
Hide it without breaking it
.skip-link {
position: absolute;
top: -10rem;
left: 1rem;
z-index: 1000;
padding: 0.75rem 1.25rem;
background: #ffffff;
color: #111111;
border: 2px solid #111111;
}
.skip-link:focus {
top: 1rem;
}
The link moves off screen by positioning, not with display:none or visibility:hidden: those values also remove it from the tab order. On focus it comes back, and the black border on white measures 21:1, above the 3:1 required by 1.4.11 Non-text Contrast, level AA. Criterion 2.4.7 Focus Visible, level AA, requires the indicator to stay visible.
How to check it in ten seconds
Load the page and press Tab once: the first highlighted element must be the skip link. Press Enter and check that focus is in the main region, then press Tab again: the first control must be inside the content, not in the menu. Tools only automate part of this, because they do not replay the sequence.
npx --yes pa11y https://example.com --standard WCAG2A
Pa11y is open source under the LGPL-3.0 licence and reports static violations with a selector and a criterion. Criterion 2.4.1 has no reliable automated test, though: a link that exists but cannot be reached still passes. The Tab sequence remains the proof.
The EneUI catalogue
EneUI indexes the accessibility category, navigation and the shadcn sidebar record, MIT licence from the shadcn/ui project. The sidebar is the typical case to skip: it stays mounted on every route and repeats dozens of links. Checked on 1 November 2026 against 111,985 components.
The limitation
A skip link serves keyboard users, not screen reader users: that group navigates by landmark and heading and rarely meets it. It replaces neither a correct heading structure nor a single <main> per page; if the main does not exist, the link has no target.
Where to continue
The operational checklist is in accessible React components; the map of roles is in what ARIA is. The comparison of navigation blocks is in the best menu blocks.
Frequently asked questions
Is a skip link mandatory?
Yes, at level A: WCAG 2.4.1 Bypass Blocks requires a mechanism to skip repeated blocks. A skip link is the simplest one, though a well-structured main with headings can also pass.
Must it be the first element in the body?
Yes, it must be the first focusable element. If another link or a button comes before it, keyboard users reach it later and the shortcut loses its point.
Why does the main have tabindex minus one?
Because focus must reach the container, not just the scroll position. tabindex="-1" makes the main focusable from code without adding it to the tab order.
Can I hide it with display none?
No. display:none and visibility:hidden also remove the link from the tab order, so it can never take focus. Move it off screen and bring it back on focus.
Is it needed in a single page application?
Yes, and you also need to move focus after a route change. In a SPA the main is the same node, so without explicit focus the screen reader never announces the new page.