QuestionsAccessibility

Heading structure & the document outline

Document StructureEasyAccessibility

Why do heading levels matter for screen readers? What are the rules for h1–h6?

What it tests

That headings are navigation, not font sizes — and the common level-skipping / styling bugs.

Approach & answer

Headings are the primary way screen-reader users navigate a page: they pull up a headings list (a rotor) and jump between sections, and they press keys to move to the next heading of a given level — exactly how a sighted reader scans bold section titles. For that to work the levels must describe a logical OUTLINE, not visual size. Rules: use one <h1> that names the page/main content; don't skip levels going down (an <h2> section's subsections are <h3>, never jumping h2→h4); and never pick a heading level for its default font size — style with CSS, choose the level by meaning. The two classic bugs are (1) using <div class="heading"> or a styled <p> that looks like a heading but has no heading role, so it's invisible to the rotor, and (2) skipping/misordering levels so the outline is nonsensical. A correct heading tree lets a user grasp the page's structure and skip to what they want in seconds; a flat or broken one forces linear reading of everything. Note the once-hoped-for HTML5 'document outline algorithm' (auto-computing levels from <section> nesting) was never implemented by browsers or AT — so explicit h1–h6 levels are still required.

Use this technique when

Structuring any page or component; catching styled-div 'headings' and skipped levels in review.

Code

<!-- Logical outline: one h1, no skipped levels -->
<h1>Account settings</h1>
  <h2>Profile</h2>
    <h3>Avatar</h3>
    <h3>Display name</h3>
  <h2>Security</h2>
    <h3>Password</h3>

<!-- WRONG: looks like a heading, but no heading role -> invisible to the rotor -->
<div class="h2-style">Security</div>

<!-- WRONG: skips h2 -> h4, breaking the outline -->
<h1>Title</h1>
<h4>Subsection</h4>

References