Command Palette

Search for a command to run...

Hectal
PHASE 2Beginner ~19 min· topic 3 of 7

Topic 2.3

Headings and the Document Outline

In one line

Headings h1 to h6 form the page's outline, a table of contents that screen-reader users navigate by; give each page one h1, nest levels by meaning, and don't skip levels.

Think of it like this

A textbook's table of contents. The book title is on the cover, chapters are numbered 1, 2, 3, and inside each chapter come sections 1.1, 1.2. You'd never find section 1.1.1 straight after Chapter 1 without a 1.1. HTML headings work the same way: h1 is the title, h2 the chapters, h3 the sections inside a chapter.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Heading
A title for a part of the page, written with h1 (most important) to h6 (least).
Heading level
The number in the heading element. It says how deep the part sits in the outline.
Document outline
The tree of headings on a page, like a table of contents.
Skipping a level
Going from one heading to one more than a level deeper, like h2 straight to h4.
Rotor
VoiceOver's menu that lists headings, links or landmarks so the user can jump to one.
Outline algorithm
An old, never-implemented HTML5 idea where sections reset heading levels. Removed from the standard in 2022.

Step by step

01Write the page title as h1

The h1 says what the whole page is about. One per page, near the top of main.

index.htmlwhole filehtml
<h1>Making soft bread at home</h1>

02Add the chapters as h2

Each major part of the page gets an h2. Think of them as the chapters in the table of contents.

index.htmlwhole filehtml
<h1>Making soft bread at home</h1>
<h2>Ingredients</h2>
<h2>Method</h2>
<h2>Common problems</h2>

03Nest sub-parts one level deeper

Inside "Common problems", each problem is a sub-part, so it gets an h3. When you return to a new major part, you go back up to h2.

index.htmlwhole filehtml
<h1>Making soft bread at home</h1>
<h2>Ingredients</h2>
<h2>Method</h2>
<h2>Common problems</h2>
<h3>Dough doesn't rise</h3>
<h3>Bread is too dense</h3>
<h2>Next steps</h2>
Nest sub-parts one level deeperdiagram
Rendering diagram…

04Match headings to sections

When you use section and article, each one usually starts with a heading one level below its parent's. The heading level comes from the depth in the outline, not from the element it sits in.

index.htmlwhole filehtml
<main>
  <h1>Making soft bread at home</h1>
  <section>
    <h2>Common problems</h2>
    <section>
      <h3>Dough doesn't rise</h3>
    </section>
  </section>
</main>

05Headings outside main

Sidebars and footers can have headings too: usually h2, because they're parts of the page alongside the main chapters. A screen-reader user pressing H meets them in source order.

06Fix size with CSS, not level

If the design wants the h3s small, keep them h3 and set their size in CSS. Level is meaning; size is looks.

style.csswhole filecss
h3 {
  font-size: 1rem;
}

Try it yourself

  1. 1

    Fix the checker's complaints

    In the second example, predict which two changes make the checker happy. Change the h4s to h3s and the second h1 to h2, then run. Only Checked 5 headings should remain.

  2. 2

    Outline a real page

    Copy the headings of a news article you like into the first example (keep their real levels from DevTools → Elements). Does its outline make sense on its own, without the body text?

  3. 3

    Navigate by headings

    If you have a screen reader (NVDA is free on Windows; VoiceOver is built into Mac with Cmd+F5), open this page and press H (NVDA) or open the rotor (VO+U on Mac) to move through its headings.

Code & diagrams

Print the outline of a page New tab

This is roughly the list a screen reader's headings menu shows. Indentation is the level.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

h1 Making soft bread at home
  h2 Ingredients
  h2 Method
  h2 Common problems
    h3 Dough doesn't rise
    h3 Bread is too dense
  h2 Next steps
A heading checker: one h1, no skipped levels New tab

Fix the HTML until the checker only prints the last line.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Problem: found 2 h1 elements, expected 1
Problem: 'Basic' is h4 after h2
Checked 5 headings

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Pick headings by size

Use <h4> for a section title because "h2 looks too big".

terminal
$ headings list in a screen reader
── what you'll see ──
heading level 1 Pricing
heading level 4 Basic (users wonder where levels 2 and 3 went)

Break #2

Rely on sections to reset levels

Use <h1> as the heading of every <section>, trusting the old HTML5 outline algorithm.

terminal
$ headings list in a screen reader
── what you'll see ──
heading level 1 (repeated for every section: a flat list with no structure)

Myth vs fact

Myth

A page must have exactly one h1 or it's invalid.

Fact

Several h1s are valid HTML. One h1 is the strong convention because it gives users and tools a clear page title.

Myth

Heading levels are for font sizes.

Fact

Levels are structure. Browsers give them default sizes, but you set the real look with CSS.

Myth

Inside a section you can start again at h1.

Fact

That relied on the outline algorithm, which nothing implemented and the standard removed in 2022. Use levels that match the real depth.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    Browsers' default stylesheets used to shrink an h1 nested inside article, aside, nav or section, a leftover from the outline algorithm. The HTML standard dropped those styles in 2025 and browsers are removing them, so always set your h1 size explicitly in CSS.

  • ▸

    aria-level can override a heading's level for assistive technology (<div role="heading" aria-level="2">), but a real h2 is always better. Web components and CMS-generated content are where you'll most often see this.

  • ▸

    Headings feed tables of contents, search-result jump links and browser reader modes. Many CMSs build a sidebar table of contents from the h2/h3 outline, so a broken outline breaks those features too.

  • ▸

    WCAG 2.2 success criterion 1.3.1 Info and Relationships requires that structure shown visually is also available in code; text that looks like a heading but is a styled p fails it.

Remember this

  1. 1

    The document outline is the tree of headings on a page: each heading starts a part, and that part lasts until the next heading of the same or a higher level. An h3 after an h2 is a sub-part of that h2; the next h2 ends both. The heading level (the number) is what builds the tree, not the font size.

  2. 2

    Use **one h1 per page** for the page's main topic: usually the same idea as the <title>, worded for people already on the page. The HTML standard allows several h1s, but one h1 is the common, recommended practice: screen-reader users often press 1 to jump to the page's main heading, and expect one.

  3. 3

    Don't skip levels going down: after an h2, the next deeper heading is an h3, not an h4. A skipped level makes users wonder whether they missed a section. Going up any number of levels is fine: an h4 can be followed by an h2 when a new chapter starts.

  4. 4

    Choose the level by meaning, never by size. If an h3 looks too big, change its size with CSS; don't swap it for an h5. And never use a heading for text that isn't a heading (a tagline, a big price): use a p and style it.

  5. 5

    Screen-reader users navigate by headings more than by anything else. In NVDA and JAWS, H jumps to the next heading and 1 to 6 to the next heading of that level; VoiceOver has a rotor that lists all headings. A clean outline lets them skim your page the way sighted users skim with their eyes.

  6. 6

    History you'll still read about: older HTML5 tutorials describe an outline algorithm where every section or article resets the levels, so you could use h1 everywhere. No browser or screen reader ever implemented it, and it was removed from the HTML standard in 2022. Always use real levels (h1–h6) that match the nesting.

Explain it without notes

01

What is the document outline, and how is it built?

02

Why shouldn't you skip heading levels, and is going up several levels at once also a problem?

03

How do screen-reader users use headings?

04

What was the HTML5 outline algorithm, and why shouldn't you rely on it?

Practice

01

Write the headings for a recipe page: page title, then Ingredients, Method (with sub-steps Preparing and Baking) and Serving.

02

This outline is broken: h1 Shop, h3 Shoes, h3 Bags, h1 Contact. Fix it.

Trade-offs

  • ↔

    Strict heading levels sometimes clash with a design where a small-looking heading must be an h2; the fix is always CSS, which costs a rule or two but keeps the structure honest.

  • ↔

    Reusable components (a card with a heading) don't know their nesting depth; teams either pass the level as a prop or pick the most common level, accepting an occasional imperfect outline.

Done when you can

  • I give each page one h1 that says what the page is about.

  • I nest headings by meaning and never skip a level going down.

  • I change heading sizes with CSS, not by changing the level.

  • I can explain how screen-reader users move through headings.

  • I know the HTML5 outline algorithm doesn't work and why.