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.