Klar Barrierefrei / wcag

WCAG 1.3.1 · rule: heading-order

How to fix skipped heading levels

Screen-reader users navigate by heading level, so a skipped or faked heading breaks the page outline. Here is how to build a hierarchy that actually nests.

Last updated: · By Paweł Dziura

Headings are an outline, not a font size

Sighted readers skim. They see a big bold line and know a new section has started. Screen-reader users skim too — but they do it by pulling up a list of every heading on the page and jumping between levels, the way you'd navigate a document by its table of contents. That only works if your headings form a logical, properly nested outline: an <h1> for the page, <h2> for each major section, <h3> for subsections, and so on, without skipping down a level. WCAG 2.1 criterion 1.3.1 (Info and Relationships, Level A) is what requires that structure to be real in the markup, not just implied by styling. The axe rule is heading-order.

Audit your page against this checklist

Before reading further, run your page through these questions. Each "no" is a likely failure:

  • Is there exactly one <h1>, describing the whole page?
  • Does every heading level follow the one above it without skipping — never an <h2> jumping straight to an <h4>?
  • Is every visually-bold "heading-looking" line an actual heading element, not a styled <div> or <p>?
  • Conversely, is every real <h2><h6> genuinely a section heading, rather than an ordinary paragraph you enlarged with a heading tag?
  • Do the levels reflect meaning — chosen for hierarchy — rather than whichever size happened to look right?

The two failures behind most of these

Almost every heading-order problem is one of two mistakes. The first is skipping levels, usually because someone picked the tag by how big it renders:

<h1>Our Pricing</h1>
<h4>Starter plan</h4>   <!-- jumps h1 → h4 because h4 looked the right size -->
<h4>Pro plan</h4>
<h1>Our Pricing</h1>
<h2>Starter plan</h2>
<h2>Pro plan</h2>

The fix is never to change the tag to match the design — it's to choose the correct level for the hierarchy and then style it with CSS to whatever size you want. Heading level and font size are independent; an <h2> can be visually small.

The second mistake is faking a heading with styling on a non-heading element, which leaves it out of the outline entirely:

<div class="section-title">Frequently asked questions</div>
<h2 class="section-title">Frequently asked questions</h2>

How our scanner detects it

We collect the page's heading elements in document order and check that the numeric levels never jump by more than one going down — an <h2> followed by an <h4> trips the heading-order rule, reported with the offending element. Here's the honest boundary: we can see the sequence of levels, but we can't read intent. We cannot tell that a bolded <div> was meant to be a heading, nor whether your one <h1> actually summarises the page well. Those judgements — is this really a heading, and does the outline make sense to a human — are things we flag for manual review rather than certify.