Skip to content

Heading Hierarchy Skip Level Fix

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about Heading Hierarchy Skip Level Fix. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

The Problem

Heading hierarchy (h1-h6) creates a document outline that screen readers use for navigation. Skipping levels (e.g., h1 to h3) breaks the outline, confusing assistive technology users who rely on heading structure to understand and navigate the page.

Quick Fix

Step 1: Use one h1 per page

<!-- Wrong — multiple h1 elements -->
<h1>Company Name</h1>
<h1>Section Title</h1>
<h1>Another Section</h1>

<!-- Right — one h1, then h2 for sections -->
<h1>Company Name</h1>
<h2>Section Title</h2>
<h2>Another Section</h2>

Step 2: Do not skip heading levels

<!-- Wrong — skipped h2 -->
<h1>Page Title</h1>
<h3>Subsection</h3>

<!-- Right — sequential levels -->
<h1>Page Title</h1>
<h2>Main Section</h2>
<h3>Subsection</h3>

Step 3: Match visual hierarchy with semantic hierarchy

<!-- Wrong — h4 styled to look like h2, but screen reader sees h4 -->
<section>
    <h4 class="heading-large">Section Title</h4>
    <p>Content here...</p>
</section>

<!-- Right — use h2 with visual styling -->
<section>
    <h2 class="heading-large">Section Title</h2>
    <p>Content here...</p>
</section>

Step 4: Use h2-h6 for subsections

<!-- Correct heading structure -->
<h1>DodaTech Tutorials</h1>

    <h2>JavaScript Basics</h2>

        <h3>Variables</h3>
        <h3>Functions</h3>

    <h2>CSS Layout</h2>

        <h3>Flexbox</h3>

            <h4>Flex Direction</h4>
            <h4>Alignment</h4>

        <h3>Grid</h3>

    <h2>Performance</h2>

Step 5: Verify heading structure programmatically

// Wrong — assuming headings are correct
// Right — audit heading structure
function auditHeadings() {
    const headings = document.querySelectorAll('h1,h2,h3,h4,h5,h6');
    const levels = Array.from(headings).map(h => parseInt(h.tagName[1]));

    if (levels[0] !== 1) {
        console.warn('First heading is not h1');
    }

    for (let i = 1; i < levels.length; i++) {
        if (levels[i] - levels[i-1] > 1) {
            console.warn('Skipped heading level:',
                headings[i-1].tagName, '→', headings[i].tagName);
        }
    }
}

Step 6: Fix heading structure in components

<!-- Wrong — component hardcodes h3, ignoring context -->
<article>
    <h3>Article Title</h3>
</article>

<!-- Right — use a flexible heading level -->
<article>
    <h2>Article Title</h2>
    <!-- Or pass heading level as a prop -->
    <div role="heading" aria-level="2">Article Title</div>
</article>

Prevention

  • Use exactly one <h1> per page
  • Never skip heading levels (do not go h1 to h3)
  • Keep heading hierarchy sequential (h1, h2, h3, h4, h5, h6)
  • Use CSS to style headings visually — do not misuse a heading level for its appearance
  • Test heading structure with browser extensions or document.querySelectorAll('h1,h2,h3,h4,h5,h6')

Common Mistakes with heading hierarchy

  1. Misunderstanding that String is [Char] with poor performance for large text operations
  2. Using foldl instead of foldl' causing stack overflow on large lists
  3. Forgetting deriving (Show, Eq) on custom data types needed for debugging

These mistakes appear frequently in real-world A11Y code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### How do I check heading hierarchy?

Use the Web Developer extension (Information > View Document Outline). Or run this in the console: document.querySelectorAll('h1,h2,h3,h4,h5,h6').forEach(h => console.log(h.tagName, h.textContent.trim())). Several Accessibility tools also audit heading structure.

Can I use role="heading" with aria-level?

Yes. If you cannot use a native heading element (e.g., in a reusable component), use role="heading" with aria-level="2". This provides the same semantics as <h2>. But prefer native heading elements when possible.

Should headings be visible or can I hide them?

Headings should be visible. Visually hiding headings for screen readers only (e.g., .sr-only) is acceptable for labeling sections that do not need visual headings, but prefer visible headings for all users.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro