Fix heading order for better accessibility
Screen reader users rely on headings to navigate your page. Skipped levels break navigation and make content structure unclear.
What's happening
Headings (<h1> through <h6>) must form a logical hierarchy, increasing by only one level at a time. Skipping from <h2> to <h4> breaks the user's mental model of the page. Users cannot tell if the skipped <h3> represents missing content or poor markup.
Ordered headings let users jump between sections, understand the page structure, and orient themselves.
Diagnose
Chrome DevTools
- Open DevTools (F12)
- Press Ctrl+Shift+P (Cmd+Shift+P on Mac)
- Type "Show headings" and select the option
- Review the heading outline - look for skipped levels
Quick console check:
const headings = [...document.querySelectorAll('h1, h2, h3, h4, h5, h6')]
let lastLevel = 0
headings.forEach((h) => {
const level = Number.parseInt(h.tagName[1])
if (level > lastLevel + 1 && lastLevel !== 0) {
console.warn(`Skipped heading level: ${h.tagName} after H${lastLevel}`, h)
}
lastLevel = level
})
Accessibility tree
- DevTools > Elements > Accessibility pane
- Expand the tree and look at heading structure
- Levels must descend sequentially: 1 > 2 > 3, not 1 > 3.
Fix
1. Restructure heading levels
Fix the hierarchy by adjusting heading levels:
<!-- Before: Skipped level -->
<h1>Product Catalog</h1>
<h3>Electronics</h3> <!-- Wrong: skipped h2 -->
<h3>Clothing</h3>
<!-- After: Sequential levels -->
<h1>Product Catalog</h1>
<h2>Electronics</h2> <!-- Correct: h2 follows h1 -->
<h2>Clothing</h2>
For nested sections, continue the hierarchy:
<h1>Product Catalog</h1>
<h2>Electronics</h2>
<h3>Phones</h3>
<h3>Laptops</h3>
<h2>Clothing</h2>
<h3>Shirts</h3>
<h3>Pants</h3>
2. Style independently from semantics
Use CSS to achieve desired visual sizes without breaking semantics:
<!-- Keep correct heading level, style differently -->
<h2 class="text-3xl font-bold">Main Section</h2>
<h3 class="text-2xl font-semibold">Subsection</h3>
<h4 class="text-xl">Nested Item</h4>
/* Override default heading styles */
.section-title {
font-size: 1.5rem;
font-weight: 600;
}
h2.section-title,
h3.section-title,
h4.section-title {
/* Same visual appearance, correct semantic level */
}
3. Fix component headings
Components often hardcode heading levels. Make them configurable:
<!-- Bad: Component always uses h3 -->
<div class="card">
<h3>Card Title</h3>
</div>
<!-- Good: Heading level is contextual -->
<div class="card">
<h2>Card Title</h2> <!-- or h3, h4 depending on context -->
</div>
Pass the heading level as a prop.
Framework examples
<script setup>
defineProps({
level: {
type: Number,
default: 2,
validator: v => v >= 1 && v <= 6
}
})
</script>
<template>
<component :is="`h${level}`" class="card-title">
<slot />
</component>
</template>
<Card>
<CardHeading :level="2">Products</CardHeading>
<Card>
<CardHeading :level="3">Electronics</CardHeading>
</Card>
</Card>
function Heading({ level = 2, children, className }) {
const Tag = `h${level}`
return <Tag className={className}>{children}</Tag>
}
// Usage with context for automatic levels
function Section({ children }) {
const parentLevel = useHeadingLevel()
return (
<HeadingLevelProvider value={parentLevel + 1}>
{children}
</HeadingLevelProvider>
)
}
SEO impact: passage ranking
Correct heading structure is critical for Google Passage Ranking.
Google indexes and ranks individual passages from a page independently. It relies on <h> tags to understand where one topic ends and another begins.
- Broken hierarchy: Confuses the crawler about the relationship between sections.
- Logical hierarchy: Allows Google to snip a specific section and serve it as a Featured Snippet.
Fixing heading order maximizes your content's surface area in search results.
Verify the fix
- Re-run Lighthouse - The "Heading elements appear in a sequentially-descending order" audit must pass.
- Check heading outline - In DevTools, run:
Array.from(document.querySelectorAll('h1,h2,h3,h4,h5,h6'), h => `${h.tagName}: ${h.textContent.trim().slice(0, 50)}`)
.join('\n')
The output must show logical nesting without skips.
- Screen reader test - Use heading navigation (H key in NVDA/JAWS) to move through headings. The structure must be logical.
Common mistakes
- Using headings for visual styling: Use a
<p>or<span>with CSS if you want big bold text that isn't a section heading. Reserve headings for actual document structure. - Multiple h1 elements: Use only one
<h1>per page. Multiple<h1>elements confuse screen readers and search engines. - Starting at h2 or h3: The first heading on a page must be
<h1>. Starting at a lower level breaks the hierarchy. - Using divs with heading roles:
<div role="heading" aria-level="2">is fragile. Use real heading elements. - Hiding headings for visual design: Use visually-hidden CSS if a heading shouldn't be visible.
display: nonehides it from screen readers.
Related issues
Heading order issues often appear alongside:
- Document Title - The title and h1 should describe the same topic
- Bypass - Proper headings enable skip navigation
- HTML Lang - Both affect how screen readers interpret structure
Test your entire site
Heading structure issues often creep in through reusable components, templates, or CMS content. A card component using <h3> might be correct on one page but break hierarchy on another. Unlighthouse scans every page and flags heading order violations across your entire site.