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.