# Tab key navigates to all interactive elements; no keyboard traps; skip links present if more than 4 nav links

- **Pattern:** `ab-001599` (`gov-section-508.keyboard-assistive.skip-links`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001599
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001599)

## Why it matters

When a page has many navigation links, every keyboard user must tab through all of them before reaching main content—on every page load. For users with motor disabilities this is fatiguing; for screen reader users it is repetitive and disorienting. Skip links solve this with a single Tab press from the top of the page. WCAG 2.2 SC 2.4.1 (Level A) requires a bypass mechanism when blocks of content are repeated across pages. SC 2.1.2 (Level A) prohibits keyboard traps that prevent users from leaving a component. Section 508 2018 Refresh 503.3.3 covers both. Navigation-heavy sites with no skip link fail their most basic keyboard-user obligation.

## Severity rationale

High because sites with navigation-heavy headers force keyboard users through significant repetitive tabbing on every page load, but they do not completely block access to content.

## Remediation

Add a skip link as the first focusable element in `app/layout.tsx`, targeting the `<main>` element by id:
```tsx
// app/layout.tsx
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <a href="#main-content" className="skip-link">
          Skip to main content
        </a>
        <Header />
        <main id="main-content">{children}</main>
        <Footer />
      </body>
    </html>
  );
}
```
Style it hidden by default, visible on focus:
```css
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: #000000;
  color: #ffffff;
  padding: 8px 16px;
  text-decoration: none;
  z-index: 9999;
}
.skip-link:focus {
  top: 0;
}
```
For modal dialogs, ensure Escape closes the modal and returns focus to the trigger element.

## Detection

- **ID:** `skip-links`
- **Severity:** `high`
- **What to look for:** Count all relevant instances and enumerate each. Check for skip links (typically a link at the top of the page that jumps to main content, hidden by default but visible on focus). Count navigation links. If more than 4, check for a visible skip link or a similar keyboard shortcut mechanism. Test that Tab key does not create loops or traps (e.g., focus cannot escape a modal or dropdown without closing it).
- **Pass criteria:** If the page has more than 4 navigation links, a skip link is present and functional (keyboard-accessible, jumps to `<main>` or primary content). At least 1 implementation must be verified. No keyboard traps exist. Pressing Tab+Shift (Shift+Tab) or Tab alone can navigate through all interactive elements without getting stuck.
- **Fail criteria:** A page with many navigation links (4+) has no skip link, or a keyboard trap exists where focus cannot escape without using the mouse.
- **Skip (N/A) when:** The page has only 1-4 navigation links and no other mechanisms that benefit from skipping (small site with minimal navigation).
- **Detail on fail:** Example: `"Navigation has 8 links (Home, About, Services, Products, Blog, Pricing, Contact, Dashboard). No skip link present. Users must tab through all 8 nav links to reach main content. Modal dialog traps focus — pressing Tab in the last button re-focuses the first button (acceptable), but pressing Escape does not close the modal."`
- **Remediation:** Add a skip link to your root layout:
  ```tsx
  <header>
    <a href="#main-content" className="skip-link">
      Skip to main content
    </a>
    <nav>{/* Navigation links */}</nav>
  </header>
  <main id="main-content">{children}</main>
  ```
  Style it to be hidden but visible on focus:
  ```css
  .skip-link {
    position: absolute;
    top: -40px;
    left: 0;
    background: #000;
    color: #fff;
    padding: 8px;
    text-decoration: none;
  }
  .skip-link:focus {
    top: 0;
  }
  ```

## External references

- wcag 2.4.1
- wcag 2.1.2
- section-508 503.3.3

Taxons: accessibility

HTML version: https://auditbuffet.com/patterns/ab-001599
