Responsive Site Header

Create accessible responsive headers that adapt from desktop navigation to mobile menu while maintaining keyboard and screen reader accessibility.

intermediate
1.3.1 Info and Relationships (Level A)2.4.1 Bypass Blocks (Level A)3.3.2 Labels or Instructions (Level A)

The Bad (Inaccessible)

<div class="header">
  <div class="logo" onclick="goHome()">Brand</div>
  <nav class="desktop-nav">
    <a href="/">Home</a>
    <a href="/about">About</a>
  </nav>
  <div class="mobile-toggle" onclick="toggleMobile()">☰</div>
</div>

Accessibility-Ready Code

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

  <div class="header-container">
    <!-- Logo -->
    <a href="/" class="logo" aria-label="Company Home">
      <img src="/logo.svg" alt="Company Logo" width="120" height="40">
    </a>

    <!-- Desktop Navigation -->
    <nav class="desktop-nav" aria-label="Main navigation">
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/about">About</a></li>
        <li><a href="/services">Services</a></li>
        <li><a href="/contact">Contact</a></li>
      </ul>
    </nav>

    <!-- Mobile Toggle -->
    <button
      type="button"
      class="mobile-toggle"
      aria-expanded="false"
      aria-controls="mobile-nav"
      aria-label="Open menu"
    >
      <span class="hamburger" aria-hidden="true">
        <span></span>
        <span></span>
        <span></span>
      </span>
    </button>
  </div>

  <!-- Mobile Navigation -->
  <div id="mobile-nav" class="mobile-nav-panel" hidden>
    <nav aria-label="Mobile navigation">
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/about">About</a></li>
        <li><a href="/services">Services</a></li>
        <li><a href="/contact">Contact</a></li>
      </ul>
    </nav>
  </div>
</header>

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

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

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

  @media (max-width: 768px) {
    .desktop-nav {
      display: none;
    }

    .mobile-toggle {
      display: flex;
      min-width: 44px;
      min-height: 44px;
    }
  }
</style>

The Standard

Responsive headers must maintain accessibility across all viewport sizes. Use semantic HTML, skip links, and proper ARIA attributes for both desktop and mobile views.

WCAG Criteria

  • 1.3.1 Info and Relationships: Semantic HTML structure.
  • 2.4.1 Bypass Blocks: Skip links to main content.
  • 3.3.2 Labels or Instructions: Clear labels for controls.

❌ The Bad (Inaccessible)

What’s Wrong?

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

✅ The Good (Accessibility-Ready Code)

Why This Works

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

Accessibility Checklist

  • Use <header role="banner"> for the site header.
  • Include skip link as first focusable element.
  • Use <a> for logo, not onclick.
  • Add aria-label="Main navigation" to desktop nav.
  • Add aria-label="Mobile navigation" to mobile nav.
  • Update mobile toggle aria-expanded dynamically.
  • Ensure mobile toggle is 44×44px minimum.
📍 Perfect Implementation Reference
<header class="site-header">
  <a href="#main" class="skip-link">Skip to content</a>

  <a href="/" aria-label="Company Home">
    <img src="/logo.svg" alt="Company Logo">
  </a>

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

  <button
    aria-expanded="false"
    aria-controls="mobile-menu"
    aria-label="Open menu"
  >

  </button>

  <div id="mobile-menu" hidden>
    <nav aria-label="Mobile navigation">
      <!-- mobile links -->
    </nav>
  </div>
</header>

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

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

  .skip-link:focus {
    top: 0;
  }
</style>

Technical Deep Dive

Screen Reader Announcements

  • NVDA: “Banner landmark, navigation landmark, Main navigation”
  • VoiceOver: “Navigation, Main navigation”
  • JAWS: “Banner region, Main navigation, navigation”

Best Practice: Semantic Landmarks

Use native HTML5 elements (header, nav, main) instead of divs with ARIA roles. The semantic elements provide landmark regions automatically, helping screen reader users navigate quickly. Only use role="banner" and role="navigation" for backwards compatibility or when working with non-semantic markup.

🧪

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