ADA Compliance Professionals

    H1 heading must lead main content

    Last updated:

    Who it helps:
    Blind
    Standard:
    WCAG 2.2 Level A

    H1 heading must exist before main content, one per page

    A page or any embedded frame needs a single level-one heading placed at the start of the main content. This enables fast heading navigation for assistive technology. It also gives a clear page topic for users with low vision or cognitive disabilities.

    Why It Matters

    Screen reader users jump to headings to understand a page quickly. Without an H1, or if it appears late, they must listen through more content to find the topic.

    People using magnification scan for large headings to orient themselves. A consistent, early H1 reduces effort and confusion.

    A coherent heading outline benefits users across frames (iframes) by keeping the structure predictable.

    Common Causes

    • No semantic h1; a styled div or span is used instead.
    • Multiple h1 elements for visual emphasis in different sections.
    • The h1 is placed after carousels, promos, or breadcrumbs within main content.
    • Single-page apps render the h1 late or only after async data loads.
    • Iframe content starts with its own h1, ignoring the parent page hierarchy.
    • role="heading" is used with an incorrect aria-level or without need.

    How to Fix

    1. Add a single h1 at the very start of the main content region.
      • Place it as the first element inside <main> (or the primary content landmark).
      • Use concise, descriptive text that states the page purpose.
    2. Maintain a logical hierarchy.
      • Use H1 for the page title, H2 for major sections, H3+ for subsections.
      • Avoid skipping levels when possible.
    3. Use semantic elements.
      • Prefer native <h1> over styling non-heading elements.
      • Only use role="heading" with aria-level when you cannot change the markup source.
    4. Integrate iframes into the parent outline.
      • If you control the embedded document, begin with H2 (or the correct level relative to the parent) rather than H1.
      • Ensure the iframe’s first heading fits under the parent page’s H1.
      • If the embedded document must also be standalone, provide an embed variant with adjusted heading levels or render heading levels conditionally.
    5. Keep the H1 early in the reading order.
      • If a hero/banner must appear visually first, include the H1 inside it or place the H1 before it in the DOM and style as needed.
    6. SPA considerations.
      • Render the H1 immediately on route change and keep document.title in sync.

    Standards note: Aligns with WCAG 2.2 principles, including 1.3.1 Info and Relationships, 2.4.6 Headings and Labels, and 2.4.10 Section Headings (AAA, advisory).

    How to Test

    Keyboard check

    • Tab into the page. Confirm the reading order places the H1 before other main content controls.
    • If a Skip to main link exists, activate it and ensure focus lands at or before the H1.

    Screen reader check

    • NVDA/JAWS (Windows): Press INSERT+F6 to open the Headings list. Verify exactly one H1, placed at the top of main content. Use H to navigate and confirm the first heading is the H1.
    • VoiceOver (macOS/iOS): Use the rotor (VO+U / two-finger rotate) to Headings. Confirm one H1 and that it appears first in the main content.
    • TalkBack (Android): Use the local context menu to list Headings and verify a single, top-level H1.

    Iframe check

    • Move focus into each iframe. Use the headings list to confirm the iframe does not begin with H1 unless it represents a standalone document. The heading level should match its position under the parent’s H1.

    Developer check

    • In DevTools console, check counts and order:
    JS
    const h1s = document.querySelectorAll('h1');
    console.log('H1 count:', h1s.length); // expect 1
    console.log('First node in <main> is H1:', document.querySelector('main')?.firstElementChild?.tagName === 'H1');

    Good Example

    HTML
    !doctype html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>City Permits | Example</title>
    </head>
    <body>
      <header>...</header>
      <main id="main">
        <h1>Apply for a City Permit</h1>
        <p>Start your online application below.</p>
    
        <section>
          <h2>Requirements</h2>
          <p>Provide identification and proof of address.</p>
        </section>
    
        <section>
          <h2>Application Form</h2>
          <iframe src="form-embed.html" title="Permit application form"></iframe>
        </section>
      </main>
      <footer>...</footer>
    </body>
    </html>
    
    <!-- form-embed.html (embedded document) -->
    !doctype html>
    <html lang="en">
    <body>
      <section>
        <h2>Permit Application</h2>
        <form>...</form>
      </section>
    </body>
    </html>

    Bad Example

    HTML
    !doctype html>
    <html lang="en">
    <body>
      <header>
        <div class="promo-carousel">...</div>
      </header>
    
      <main>
        <div class="page-title" style="font-size:2rem">Apply for a City Permit</div>
    
        <section>
          <h1>Requirements</h1>
          <p>...</p>
        </section>
    
        <section>
          <h1>Application</h1>
          <iframe src="form-embed-bad.html" title="Form"></iframe>
        </section>
      </main>
    </body>
    </html>
    
    <!-- form-embed-bad.html (embedded document) -->
    !doctype html>
    <html lang="en">
    <body>
      <h1>Permit Application</h1>
      <form>...</form>
    </body>
    </html>

    Quick Checklist

    • Exactly one H1 per page or frame.
    • H1 is the first element of the main content region.
    • H1 text clearly states the page topic.
    • Section headings follow a logical H1 > H2 > H3 outline.
    • Iframes start at H2 (or appropriate level) relative to the parent.
    • Do not rely on styling alone; use semantic heading elements.
    • In SPAs, render the H1 immediately on route load.
    • Verify with a screen reader’s Headings list before release.