Skip to content

How to fix: Headings must follow a logical order

Heading levels should not skip (an h2 followed by an h4). The heading structure is how many assistive-tech users navigate a page.

The fix

Use heading levels in order (do not skip from <h2> to <h4>) to keep a logical outline.

Who this affects

This is an axe best-practice rule with no single success criterion behind it, so it will not fail a conformance audit on its own. It still matters: in WebAIM's 2024 screen reader survey, 71.6% of respondents said walking the headings is their first move on a long page, and a jump from h2 to h4 tells a listener that a subsection sits inside a section that was never announced. Users who press 2 or 3 to move between sections of a given rank skip straight past any block whose level does not line up.

Before and after

Fails
<h2>Products</h2> … <h4>Reviews</h4>
Passes
<h2>Products</h2> … <h3>Reviews</h3>

Where this usually comes from

  • The heading level is picked for its default font size, so an h4 is used because the designer wanted smaller text.
  • A design-system Heading component ties visual size and semantic level to one prop, so size="sm" also renders an h5.
  • A content block is reused across templates: a card that opens at h3 fits under an h2 section and skips a level when dropped directly beneath the h1.
  • CMS editors choose from a WYSIWYG dropdown offering Heading 1 to Heading 6 with no indication of what precedes their block on the page.
  • A visually hidden heading added for screen readers, such as a "Main navigation" h2 no sighted reviewer sees, sits at a level that clashes with the visible outline.

Checking it yourself

Run $$('h1,h2,h3,h4,h5,h6').map(h => h.tagName + ' ' + h.textContent.trim()) in the DevTools Console and read the result top to bottom as an outline; each step down should move one level at a time. With NVDA, press H repeatedly to walk the same list, or open the Elements List with NVDA+F7 and choose Headings, which nests every heading under the one above it, so a skipped level shows as a jump in indentation. The check always passes the first heading on the page whatever its level, so an outline that opens at h3 needs your own eye rather than the scanner's.

A scanner finds this one automatically. What it cannot judge, and how the score is built, is on how we test.

Related fixes

Check your site for this issue

Scan any page free against WCAG 2.2 AA and get every automatically detected issue with its fix.

Scanning a page needs no account. The checks run on axe-core.

← All fix guides