About This Accessibility Rule
Screen readers and keyboard-only navigation process page content sequentially, following the DOM order. This means that everything before the main content — site logos, navigation bars, search forms, utility links — must be traversed before a user reaches what they actually came for. On complex sites, this repetitive content can be extremely lengthy.
A properly functioning skip link gives these users a shortcut. When the skip link’s target is missing or not focusable, activating the link does nothing. The user remains at the top of the page with no indication of what went wrong, which is both confusing and frustrating.
This issue primarily affects:
- Blind and deafblind users who rely on screen readers to navigate sequentially.
- Keyboard-only users (including those with mobility impairments) who tab through every interactive element.
- Sighted keyboard users who benefit from the visual skip link appearing on focus.
This rule is a Deque best practice and aligns with WCAG technique G1 (“Adding a link at the top of each page that goes directly to the main content area”), which supports WCAG 2.4.1 Bypass Blocks (Level A). Success Criterion 2.4.1 requires that a mechanism exists to bypass blocks of content repeated across multiple pages.
How to Fix It
-
Add a skip link as the very first focusable element inside the
<body>tag, before any navigation or repeated content. -
Set the
hrefto a fragment identifier (e.g.,#main-content) that matches theidof the target element. -
Ensure the target element exists in the DOM with the corresponding
id. -
Make the target focusable if it is not natively focusable. Non-interactive elements like
<div>or<main>needtabindex="-1"so the browser can move focus to them when the skip link is activated. -
Do not hide the skip link with
display: noneorvisibility: hidden, as these make the link inaccessible to all users, including screen reader users.
Handling the Skip Link’s Visibility
You can make the skip link visually hidden until it receives keyboard focus. This approach keeps the layout clean for mouse users while remaining fully accessible to keyboard users:
- Use CSS to position the link off-screen by default.
-
On
:focus, bring it back on-screen so sighted keyboard users can see it.
Alternatively, you can make the skip link permanently visible — this is the simplest and most inclusive approach.
Important: Never use display: none or visibility: hidden on the skip link. These properties remove the element from the accessibility tree and the tab order, making it useless for everyone.
Examples
Incorrect: Skip Link Target Does Not Exist
The skip link points to #main-content, but no element with that id exists on the page.
<body>
<a href="#main-content">Skip to main content</a>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
<main>
<h1>Welcome</h1>
<p>Page content goes here.</p>
</main>
</body>
Incorrect: Target Exists but Is Not Focusable in Some Browsers
Some older or WebKit-based browsers may not move focus to a non-interactive element even with a matching id, unless tabindex="-1" is added.
<body>
<a href="#main-content">Skip to main content</a>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
<div id="main-content">
<h1>Welcome</h1>
<p>Page content goes here.</p>
</div>
</body>
Correct: Skip Link with a Focusable Target
The target element has both a matching id and tabindex="-1" to ensure it receives focus reliably across all browsers.
<body>
<a href="#main-content" class="skip-link">Skip to main content</a>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
<main id="main-content" tabindex="-1">
<h1>Welcome</h1>
<p>Page content goes here.</p>
</main>
</body>
Correct: Skip Link That Is Visually Hidden Until Focused
This CSS pattern hides the skip link off-screen by default and reveals it when the user tabs to it.
<body>
<a href="#main-content" class="skip-link">Skip to main content</a>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
<main id="main-content" tabindex="-1">
<h1>Welcome</h1>
<p>Page content goes here.</p>
</main>
</body>
.skip-link {
position: absolute;
left: -9999px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
.skip-link:focus {
position: static;
width: auto;
height: auto;
overflow: visible;
padding: 8px 16px;
background: #ffc;
border: 2px solid #990000;
z-index: 1000;
}
What the Rule Checks
This axe-core rule (skip-link) verifies that every skip link on the page — typically the first link in the document — has a target that both exists in the DOM and is focusable. If the href points to a fragment identifier like #main-content, the rule confirms that an element with id="main-content" is present and can receive focus.
Help us improve our guides
Detect accessibility issues automatically
Rocket Validator scans thousands of pages with Axe Core and the W3C Validator, finding accessibility issues across your entire site.