Site Header with Skip Links

Create an accessible site header with skip links for keyboard users. Ensure navigation landmarks are properly labeled and organized.

beginner
2.4.1 Bypass Blocks (Level A)1.3.1 Info and Relationships (Level A)4.1.2 Name, Role, Value (Level A)
❌

The Bad (Inaccessible)

<div class="header">
  <div class="logo" onclick="location.href='/'">Brand</div>
  <div class="nav">
    <a href="/">Home</a>
    <a href="/about">About</a>
  </div>
</div>
βœ…

Accessibility-Ready Code

<!-- Gold Standard: Semantic header with landmarks -->
<a href="#main-content" class="skip-link">Skip to main content</a>

<header class="site-header">
  <div class="header-container">
    <!-- Logo with proper link -->
    <a href="/" class="logo" aria-label="Company Home">
      <img src="/logo.svg" alt="" width="150" height="50">
      <span class="sr-only">Company</span>
    </a>

    <!-- Primary navigation -->
    <nav id="navigation" aria-label="Main navigation">
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/about">About Us</a></li>
        <li><a href="/products">Products</a></li>
        <li><a href="/services">Services</a></li>
        <li><a href="/contact">Contact</a></li>
      </ul>
    </nav>

    <!-- Secondary actions -->
    <div class="header-actions">
      <a href="/search" aria-label="Search">
        <svg aria-hidden="true" width="20" height="20">πŸ”</svg>
      </a>
      <a href="/cart" aria-label="View cart (3 items)">
        <svg aria-hidden="true" width="20" height="20">πŸ›’</svg>
        <span class="cart-count">3</span>
      </a>
    </div>
  </div>
</header>

<!-- Main content -->
<main id="main-content">
  <h1>Welcome</h1>
</main>

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

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

  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
  }
</style>

The Standard

Site headers provide navigation and branding. They must include skip links for keyboard users and proper landmark roles for screen readers.

WCAG Criteria

  • 2.4.1 Bypass Blocks: Skip links to main content.
  • 1.3.1 Info and Relationships: Semantic HTML structure.
  • 4.1.2 Name, Role, Value: Proper ARIA roles.

❌ The Bad (Inaccessible)

What’s Wrong?

  1. No skip links: Keyboard users must tab through nav every page.
  2. Using div for header: No landmark for screen readers.
  3. Missing nav labels: Screen readers can’t identify purpose.
  4. onclick on logo: Not keyboard accessible.

βœ… The Good (Accessibility-Ready Code)

Why This Works

  1. Skip Link: Lets keyboard users bypass repeated navigation.
  2. Semantic <header>: Creates a banner landmark.
  3. Labeled Navigation: aria-label identifies the nav’s purpose.
  4. Proper Logo Link: Uses <a> instead of onclick.

Accessibility Checklist

  • Add skip link as first focusable element in page.
  • Use <header role="banner"> for site header.
  • Use <nav aria-label="Main navigation"> for primary nav.
  • Make logo an <a> link, not onclick.
  • Add aria-label to icon-only links (search, cart).
  • Include item count in aria-label when relevant.
πŸ“ Perfect Implementation Reference
<a href="#main" class="skip-link">Skip to content</a>

<header role="banner">
  <a href="/" aria-label="Company Home">
    <img src="/logo.svg" alt="">
    <span class="sr-only">Company</span>
  </a>

  <nav aria-label="Main navigation">
    <ul>
      <li><a href="/">Home</a></li>
      <li><a href="/about">About</a></li>
    </ul>
  </nav>

  <div class="header-actions">
    <a href="/search" aria-label="Search">
      <svg aria-hidden="true">...</svg>
    </a>
    <a href="/cart" aria-label="View cart (3 items)">
      <svg aria-hidden="true">...</svg>
      <span>3</span>
    </a>
  </div>
</header>

<main id="main">
  <h1>Welcome</h1>
</main>

<style>
  .skip-link {
    position: absolute;
    top: -40px;
  }

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

  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
  }
</style>

Technical Deep Dive

Screen Reader Announcements

  • NVDA: β€œSkip to main content link, banner landmark, Main navigation navigation”
  • VoiceOver: β€œSkip to main content, link, navigation, Main navigation”
  • JAWS: β€œSkip to main content, link, banner region, Main navigation”

Skip links should be visually hidden until they receive focus, then become visible. This is achieved using position: absolute; top: -40px to move the link off-screen, and top: 0 on :focus to bring it into view. Ensure skip links have a high z-index so they appear above all other content when focused.

πŸ§ͺ

Interactive Behavioral Lab

πŸ’»

Interactive Sandbox

LIVE PREVIEW

πŸ”¬ Technical Internals

Understand how this component is processed by the browser and Assistive Technology (AT). This section bridges the gap between visual code and the hidden logic that powers accessibility.

🌲 Accessibility Tree

The data structure used by screen readers to "see" your page. It translates HTML roles and attributes into standardized objects.

βš™οΈ Event Logic

Expected behavioral standards for keyboard navigation and state transitions. Crucial for users who don't use a mouse.

  • Focus: Highlights via :focus-visible
  • Activation: Responds to Enter and Space
  • Role: Identified as Landmark

🌐 Browser & Screen Reader Compatibility

Browser
Screen Reader
Status
🍎 Safari
VoiceOver
βœ“ Safe
πŸͺŸ Chrome
NVDA
βœ“ Safe
πŸͺŸ Edge
JAWS
βœ“ Safe
🦊 Firefox
NVDA
βœ“ Safe
πŸ“± iOS Safari
VoiceOver
βœ“ Safe
πŸ€– Chrome Android
TalkBack
βœ“ Safe