squirrelscan
GitHub

Heading order: why skipping from h1 to h3 matters

Screen reader users navigate by heading level, and a skipped level makes the outline harder to follow. squirrel checks document order on every page.

What heading order is

Heading levels are an outline, not a type scale. A screen reader user pressing 2 moves between second-level headings and expects everything under one of them to belong to it. Skipping from <h1> to <h3> implies a missing section, and the user has to guess whether they missed something.

Going back up a level is not a skip. An <h3> followed by an <h2> closes one section and opens the next.

What squirrel checks

One check, heading-order, at severity warning. It reads every <h1> through <h6> in document order and compares each level with the one before it.

  • Warn when a heading is more than one level deeper than its predecessor. Report message: N heading level skip(s) detected. Every skip is listed, as H3 after H1.
  • Pass with Heading levels follow correct order.
  • Info with No headings found.

The first heading on a page is never counted as a skip, whatever its level, so a page that starts at <h3> passes this check. Whether the page has a top-level heading at all is core/h1.

How to fix it

<h1>Pricing</h1>
<h2>Plans</h2>
<h3>Team</h3>
<h2>Frequently asked questions</h2>

Pick the level from the position in the outline and set the size in CSS. If an <h3> looks right because you want smaller text, style the <h2> instead.

Two independent components stacked on a page are the usual source. Each renders a sensible internal outline, and the combination skips a level at the seam. Passing the starting level into the component as a prop solves it.

Rule IDa11y/heading-order
CategoryAccessibility
ScopePer-page
Severitywarning
Weight4/10

Enable / disable

Disable this rule

[rules]
disable = ["a11y/heading-order"]

Disable all Accessibility rules

[rules]
disable = ["a11y/*"]

Enable only this rule

[rules]
enable = ["a11y/heading-order"]

enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.

Accessibility findings ship in every audit next to the SEO, performance and agent experience rules. See Website security scan with AI for how an agent works through a report.

References

Check your site

Run squirrel audit https://example.com and open the Accessibility section of the report. Each skip is listed with the level that jumped and the level before it. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.

Type to search…

↑↓ navigate↵ openesc close