No skip link (keyboard:skip-link)

The keyboard:skip-link rule flags a page whose first Tab stop is not a working link to the main content. Keyboard users then tab through the logo, the whole menu and the search on every page before they reach anything new. The fix is a "Skip to content" link as the first focusable element, pointing at an element that exists.

What the rule means

WCAG 2.4.1 requires a mechanism to bypass blocks of content that repeat on every page. Strictly, landmarks and headings are recognised ways to meet it – but they only help people whose software can jump by landmark or heading, which is mainly screen reader users. For a sighted person using the keyboard, a skip link is the mechanism: one Tab, one Enter, and they are past the navigation.

A skip link may be hidden until it takes focus. It has to become visible then, and its target has to exist.

Who is affected

Sighted keyboard users – people with motor disabilities using a keyboard, switch or mouth stick, and people with low vision using a magnifier. A site navigation of thirty links means thirty Tab presses on every page, and with a switch every press is slow and tiring.

Why the check fails

  • No skip link at all – the first Tab lands on the logo.
  • A skip link that is not first, behind a cookie banner, a language switcher or a "call us" link.
  • A broken target: href="#main" while the content has id="content", or no id at all.
  • href="#" or a script-driven button instead of a same-page link.
  • Themes and templates that shipped a skip link and a later redesign removed.

How to fix it

Make the skip link the first element in <body>, point it at the main content and give that element the id.

<!-- Before: the first Tab lands on the logo -->
<body>
  <header>
    <a href="/"><img src="/logo.svg" alt="Example Ltd – home"></a>
    <nav aria-label="Main menu">
      <a href="/products/">Products</a> <a href="/contact/">Contact</a>
    </nav>
  </header>
  <main><h1>Our products</h1></main>
</body>
<!-- After: a skip link first, pointing at an element that exists -->
<body>
  <a class="skip-link" href="#content">Skip to content</a>
  <header>
    <a href="/"><img src="/logo.svg" alt="Example Ltd – home"></a>
    <nav aria-label="Main menu">
      <a href="/products/">Products</a> <a href="/contact/">Contact</a>
    </nav>
  </header>
  <main id="content"><h1>Our products</h1></main>
</body>

Hide it until it is needed, and bring it into view on focus:

.skip-link { position: absolute; left: -9999px; }
.skip-link:focus { left: 1rem; top: 1rem; padding: .5rem 1rem; background: #ffffff; color: #1a1a1a; }

How to test it manually

  1. Load the page, click into the address bar and press Tab once. Does a "Skip to content" link appear?
  2. Press Enter. Does the page move to the main content, and does the next Tab continue from there?
  3. Check the link is the first Tab stop on every template – home, category, article, checkout.
  4. Check it stays visible while it has focus, also at mobile width.

2.4.1 Bypass Blocks, Level A. Related: 2.4.3 Focus Order and 1.3.1 Info and Relationships, where landmarks and headings give screen reader users their own way past the navigation.

How Reviseberg reports it

This rule comes from Reviseberg's keyboard agent, not from axe-core. Before pressing any key, the agent looks at the first focusable element on the page. It passes if that element is a link to #something and an element with that id exists; otherwise the page fails with "The page offers no way to skip the repeated navigation", and the first step of the keystroke trail says why – no link at all, or a link to a target that does not exist.

That is all it checks. It does not test whether the target is the main content, whether the link becomes visible on focus (the next Tab step shows that, reported as undefined), or whether landmarks already serve screen reader users. That is why the finding is reported at the lowest severity. If you decide your page meets 2.4.1 another way, record the decision on the finding with your reason.

  • undefined – the page has no main landmark for screen reader users to jump to.
  • undefined – content outside landmarks.
  • undefined – a skip link that never comes into view.

Run the keyboard agent on your site – free report

Frequently asked questions

Is a skip link required by WCAG?

Not by name. 2.4.1 asks for a way to bypass repeated blocks, and landmarks or headings can meet it for screen reader users. For sighted keyboard users, a skip link is the practical way.

Can the skip link be invisible?

Until it takes focus, yes. It has to appear when it is focused.

Where should it point?

At the start of the main content, usually <main id="content">. The target needs the id; nothing else is required in current browsers.

What if my page has several skip links?

The agent only checks the first focusable element. More links (to the search, to the footer) are fine as long as the first one works.

Sources

  1. W3C, Understanding SC 2.4.1 Bypass Blocks – https://www.w3.org/WAI/WCAG22/Understanding/bypass-blocks
  2. W3C, Technique G1: Adding a link at the top of each page that goes directly to the main content area – https://www.w3.org/WAI/WCAG22/Techniques/general/G1
  3. WebAIM, Skip Navigation Links – https://webaim.org/techniques/skipnav/

See what a scan finds on your site

One page in about thirty seconds, no email needed. The full report covers up to 100 pages and a keyboard journey.