H1 heading must lead main content
Last updated:
Related Guides
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 incorrectaria-levelor without need.
How to Fix
- 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.
- Place it as the first element inside
- Maintain a logical hierarchy.
- Use H1 for the page title, H2 for major sections, H3+ for subsections.
- Avoid skipping levels when possible.
- Use semantic elements.
- Prefer native
<h1>over styling non-heading elements. - Only use
role="heading"witharia-levelwhen you cannot change the markup source.
- Prefer native
- 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.
- 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.
- 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:
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
!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
!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.