Fix Missing Bypass Blocks for Keyboard Navigation

Learn how to fix bypass issues in Lighthouse accessibility audits
Harlan WiltonHarlan Wilton4 min read Published

Keyboard users must tab through every navigation link on every page visit without a way to skip to main content.

What's Happening

Most websites have navigation menus with 10, 20, or more links. Keyboard users must press Tab for each link before reaching the main content. On a site with 30 nav links, that's 30 key presses per page. Bypass mechanisms—skip links, headings, and landmark regions—let users jump directly to what they need. WCAG requires at least one bypass method for pages with repeated blocks of content.

Diagnose

  1. Open your page in a browser
  2. Press Tab once—does a "Skip to main content" link appear?
  3. Check if you have a proper heading structure (at least one <h1>)
  4. Inspect the HTML for landmark regions: <main>, <nav>, <header>, <footer>
  5. If none of these exist, you'll fail this audit

Use a screen reader's landmarks navigation (NVDA: D key, VoiceOver: rotor) to verify landmarks are recognized.

Fix

Place a skip link as the first focusable element on the page:

<body>
  <a href="#main-content" class="skip-link">
    Skip to main content
  </a>

  <header>
    <nav><!-- 20+ navigation links --></nav>
  </header>

  <main id="main-content">
    <!-- Page content -->
  </main>
</body>

Style the skip link to be visible only on focus:

.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  padding: 8px 16px;
  background: #000;
  color: #fff;
  z-index: 100;
  transition: top 0.2s;
}

.skip-link:focus {
  top: 0;
}

2. Use Semantic Landmark Regions

Screen readers can navigate by landmarks directly:

<body>
  <header role="banner">
    <nav role="navigation" aria-label="Main">
      <!-- Navigation links -->
    </nav>
  </header>

  <main role="main">
    <h1>Page Title</h1>
    <!-- Main content -->
  </main>

  <aside role="complementary">
    <!-- Sidebar content -->
  </aside>

  <footer role="contentinfo">
    <!-- Footer content -->
  </footer>
</body>

Note: Modern browsers don't require explicit roles on semantic elements, but they don't hurt.

3. Include a Proper Heading Structure

Every page should have at least one heading:

<main id="main-content">
  <h1>Welcome to Our Site</h1>

  <section>
    <h2>Featured Products</h2>
    <!-- Content -->
  </section>

  <section>
    <h2>Latest News</h2>
    <!-- Content -->
  </section>
</main>

Screen reader users can press H to jump between headings, providing another bypass method.

4. Multiple Navigation Landmarks

When you have multiple <nav> elements, label them:

<nav aria-label="Main navigation">
  <!-- Primary nav links -->
</nav>

<nav aria-label="Breadcrumb">
  <!-- Breadcrumb links -->
</nav>

<nav aria-label="Footer navigation">
  <!-- Footer links -->
</nav>

Framework Examples

In Nuxt, add the skip link to your default layout:
<!-- layouts/default.vue -->
<template>
  <div>
    <a href="#main-content" class="skip-link">
      Skip to main content
    </a>

    <AppHeader />

    <main id="main-content">
      <slot />
    </main>

    <AppFooter />
  </div>
</template>

<style>
.skip-link {
  @apply absolute -top-10 left-0 bg-primary text-white px-4 py-2 z-50 focus:top-0 transition-[top];
}
</style>
This ensures every page in your Nuxt app has a skip link without duplicating code.

Verify the Fix

  1. Re-run Lighthouse accessibility audit
  2. Load the page and press Tab once—the skip link should appear
  3. Press Enter on the skip link—focus should move to main content
  4. Test with a screen reader:
    • Use landmark navigation to verify regions are recognized
    • Use heading navigation (H key) to jump between sections
  5. Check multiple pages—bypass mechanisms should be consistent

Common Mistakes

  • Skip link goes nowhere — The href="#main-content" must match an element's id.
  • Skip link hidden with display:none — This removes it from tab order. Use positioning instead.
  • Missing id on main content — The skip link target must exist: <main id="main-content">.
  • Only having headings, no landmarks — While this can pass the audit, landmarks provide better navigation for screen reader users.
  • Using div instead of semantic elements<div class="main"> isn't a landmark. Use <main> or add role="main".

What Satisfies This Audit

Lighthouse looks for at least one of:

  • A heading element (<h1> through <h6>)
  • A skip link (<a> with an anchor reference early in the DOM)
  • A landmark region (<main>, <nav>, <header>, <footer>, or elements with landmark roles)

For the best user experience, implement all three: skip link, proper headings, and semantic landmarks.

Bypass issues often appear alongside:

  • Heading Order — Proper headings enable keyboard navigation by section
  • Tabindex — Both affect how keyboard users navigate the page
  • Link Name — Skip links need accessible names too

Test Your Entire Site

Navigation structure and bypass blocks should be consistent across your site. Unlighthouse audits every page to ensure your skip links work everywhere, your heading structure is consistent, and all pages have proper landmark regions for screen reader navigation.