Quick answer: This audit fails when headings skip a level, such as an h1 followed directly by an h3. Fix it by choosing heading tags by document hierarchy rather than visual size, using exactly one h1, never skipping a level downward, and styling text size with CSS instead.
This Lighthouse audit fails when your page skips heading levels, for example, an <h1> followed by an <h3> with no <h2> between them. Screen readers expose the heading hierarchy as a document outline; skipped levels break that outline.
TL;DR
- What: Heading levels (h1 → h2 → h3 → h4...) must not skip a level downward.
- Why it matters: Screen reader navigation by heading is broken when levels jump.
- Fix: Use heading tags by semantic level, not by visual size. Style with CSS, not with which tag you pick.
What does the heading-order audit check?
Lighthouse walks the rendered DOM in source order and inspects every heading (<h1>–<h6>). It flags pages where a heading is more than one level lower than the previous one.
<h1>Page title</h1>
<h3>Subheading</h3> <!-- ❌ skipped h2 -->
Going back up is fine, <h3> followed by <h2> is OK. The audit only fails on downward jumps.
Why does heading order matter?
Screen readers expose page structure as a navigable outline. Users press H (or NVDA: 1, 2, 3 keys for specific levels) to jump between sections. When levels are skipped, the outline reads as: "Page title (level 1), Subheading (level 3, level 2 missing)." It implies there's a level 2 they missed, which is confusing.
It also hurts SEO subtly: Google's structured understanding of your page relies in part on the heading outline.
How do I fix heading order?
Use heading levels semantically, not visually. Pick the tag for what the content means, then size it with CSS.
<!-- BEFORE: tag chosen for visual size -->
<h1>Our pricing plans</h1>
<h3>Free tier</h3>
<h3>Pro tier</h3>
<!-- AFTER: semantic hierarchy -->
<h1>Our pricing plans</h1>
<h2>Free tier</h2>
<h2>Pro tier</h2>
If you want <h2> to look smaller than the original <h3>, do that in CSS:
h2 { font-size: 1.5rem; font-weight: 600; }
What are common heading-order scenarios?
Scenario: Card grids inside a section
<section>
<h2>Features</h2> <!-- correct level for the section -->
<article>
<h3>Real-time sync</h3> <!-- h3 because it's nested in h2's section -->
<p>...</p>
</article>
<article>
<h3>Offline mode</h3> <!-- also h3, sibling article -->
<p>...</p>
</article>
</section>
Scenario: Sidebar with its own headings
The page's main <main> outline doesn't include <aside> content. You can restart heading levels inside an <aside> if you want, but most accessibility experts recommend continuing the document hierarchy.
Scenario: Component libraries (e.g. design systems)
If your design system exports a <Card> component that hard-codes <h3> internally, you'll break heading order whenever you use it inside a section that doesn't have an h2. Solution: make the heading level a prop.
<Card heading="h2" title="Feature name" />
What heading-order pitfalls should I avoid?
- Don't have more than one
<h1>. HTML5 technically allows it via sectioning, but Lighthouse and screen readers expect one h1 per page. - Don't use
<h1>for branding/logo. That's what the<header>element + alt text is for. - Don't pick a heading tag because of its default size. Use CSS for sizing.
How do I verify heading order?
- Re-run Lighthouse. The
heading-orderaudit should pass. - View the document outline with a screen reader's heading list (VoiceOver: VO+U → Headings; NVDA: NVDA+F7).
- Use a browser extension like "Headings Map" or axe DevTools to visualize the heading tree.
Related audits
- Document does not have a main landmark, landmark structure
- Image alt attributes, screen reader content
- Meta description, SEO
Audit your URL at https://lighthouse-md.com.
Audit your page now
Paste your URL, get scores plus a CLAUDE.md plan for Claude Code.