Skip to content
academia.sh

Lesson 08 / 25

Heading Hierarchy

Heading level's function as a structural declaration, extracting the document's outline, the consequence of skipping a level, and headings' use as a navigation tool.

Contents

The head section is complete; writing the body begins. The body’s first structural decision is headings: the tags that declare which sections the document is divided into and these sections’ level relative to one another.

There are six heading elements: h1 through h6. The number gives the heading’s level — the first level is the topmost. This number is not a font size; it declares nesting depth.

A Heading Is a Structural Declaration

A heading element does two jobs. It names the content that follows it, and it declares that content’s depth in the document. The second job is carried by the level number.

It is enough to think of a book’s table of contents: chapter titles, section titles, and subsection titles are written at different indentation levels, and the indentation shows which subsection belongs to which chapter. In HTML, the level number is indentation’s counterpart.

This information is used. Screen readers offer navigation from heading to heading; instead of listening to the document from the start, the user scans the outline and jumps to the section they are interested in. Content-extraction tools divide the document by its headings. Indexers give heading text a different weight than body text.

Extracting the Outline

Heading levels define a tree, and this tree can be computed from the document.

// heading.mjs — extracts the outline from a heading-level sequence
const document_ = `
<h1>North Slope Station</h1>
<h2>Location</h2>
<h2>Measured Quantities</h2>
<h3>Temperature</h3>
<h3>Relative Humidity</h3>
<h2>Data Access</h2>
<h4>File Format</h4>
`;

const headings = [...document_.matchAll(/<h([1-6])>([^<]*)<\/h\1>/g)].map((e) => ({
  level: Number(e[1]),
  text: e[2],
}));

let previous = 0;
const warnings = [];
const number = [];
for (const heading of headings) {
  if (previous !== 0 && heading.level > previous + 1) {
    warnings.push(`h${previous} then h${heading.level}: h${previous + 1} skipped (${heading.text})`);
  }
  number.length = heading.level;
  number[heading.level - 1] = (number[heading.level - 1] ?? 0) + 1;
  const label = [...number].map((s) => s ?? 0).join(".");
  console.log("  ".repeat(heading.level - 1) + label + "  " + heading.text);
  previous = heading.level;
}

console.log("--- audit ---");
console.log("heading count :", headings.length);
console.log("h1 count      :", headings.filter((b) => b.level === 1).length);
for (const warning of warnings) console.log("warning       :", warning);
1  North Slope Station
  1.1  Location
  1.2  Measured Quantities
    1.2.1  Temperature
    1.2.2  Relative Humidity
  1.3  Data Access
      1.3.0.1  File Format
--- audit ---
heading count : 7
h1 count      : 1
warning       : h2 then h4: h3 skipped (File Format)

The last heading makes the flaw visible. While Data Access is at the second level, File Format was written at the fourth level; the third level was skipped. In the numbering, this shows up as an empty digit, in the form 1.3.0.1: there is a level in the outline with no counterpart.

The Consequence of Skipping a Level

A skipped level leaves a gap in the outline. A user navigating the document from heading to heading expects a subsection that does not exist between Data Access and File Format, and does not find it. The result is not a visual flaw, it is a wrong structural declaration.

The reason for the skip is usually presentational: the author found a fourth-level heading’s default appearance more suitable. This is the layer violation defined in the first lesson. The correct fix is to choose the level by structure and correct the appearance in the presentation layer.

There is no rule in the reverse direction: skipping while the level decreases is not a flaw. Returning to the second level after a third-level section declares that the subsection has ended and a new higher-level section has begun; this is an ordinary closing.

How Many First-Level Headings in a Document

There are two defensible approaches on this question, and both are in use.

The single-h1 approach: the document has only one first-level heading, and it names the document’s subject. Everything else is beneath it. This approach makes the outline a single-rooted tree and makes it easy to summarize the document outside its context.

The per-section-h1 approach: every sectioning element restarts its own heading level, and level is computed from nesting. The outline computation this approach relies on has not been consistently supported across screen-reader implementations.

This course follows the first approach: a single h1 in the document, with headings beneath it that follow numeric order. The justification is not theoretical superiority, it is that implementations interpret this arrangement consistently. A structural declaration’s value depends on the tools reading it drawing the same conclusion from it.

A Heading’s Content

A heading element carries text and allows inline markup: a heading can contain an abbreviation, a code fragment, or emphasis. What it should not contain is content that belongs to a separate section — a heading names a section, it is not the section’s content itself.

Heading text should also be understandable outside its context. A user navigating from heading to heading hears only the headings, without seeing the body text. Headings like “Details,” “More,” or “Section 3” carry no information in this use.

If a document has text that is not written with a heading element but visually stands like a heading, that section is not in the outline. The reverse holds too: text placed in a heading element only to look large adds a section to the outline that does not exist.

The Subheading Problem

Writing a short introductory line beneath a heading, one that complements it, is a common requirement. If this line is placed in a second-level heading element, a section that does not exist is added to the outline: while navigating, the user expects a subsection, but there is only an introductory sentence.

<h1>North Slope Measurement Station</h1>
<h2>At 1840 meters, four quantities</h2>   <!-- adds a fake section to the outline -->

The correct way to write it leaves the introductory line outside the heading element and keeps the two together:

<header>
  <h1>North Slope Measurement Station</h1>
  <p>At 1840 meters, four quantities</p>
</header>

Here the outline has only one entry; the introductory line is a paragraph, and its visual relationship with the heading is established in the presentation layer. The header element used here is the subject of the next topic; its job here is to group the two elements as a single introductory block.

The same reasoning applies to opening a second heading element just to show part of the heading text smaller. If an entry is meant to be added to the outline, a heading element is used; if not, it is not used. Appearance is not the criterion for this decision.

The Station Document’s Outline

The body of the document developed throughout the course is divided into sections with headings:

<body>
  <h1>North Slope Measurement Station</h1>
  <p>An automated measurement station built at an elevation of 1840 meters above sea level.</p>

  <h2>Location and Setup</h2>
  <p>The station sits on the middle stretch of a north-facing slope.</p>

  <h2>Measured Quantities</h2>
  <h3>Temperature</h3>
  <p>The measurement interval is ten minutes.</p>
  <h3>Relative Humidity</h3>
  <p>The measurement interval is ten minutes.</p>

  <h2>Data Access</h2>
  <p>Records are published as daily files.</p>
</body>

This skeleton is the structure the rest of the document will be built on. In the following lessons, each section’s content will be filled in; the heading arrangement will not change.

Summary

  • Heading level is not a font size, it is structural data that declares depth in the document.
  • Headings define an outline; this outline is used by navigation, content-extraction, and indexing tools.
  • Skipping while level increases leaves a gap in the outline with no counterpart; skipping while level decreases is not a flaw.
  • The approach of keeping a single first-level heading in the document is followed in this course because of implementations’ consistent interpretation.
  • Heading text should be understandable outside its context too; a user navigating from heading to heading does not see the body.

Next Step

Headings named the sections; paragraphs will fill their content. Paragraph text itself is structureless too: why a piece is emphasized, what an abbreviation stands for, where a quotation comes from is lost unless declared. The next lesson takes up inline markup, and along the way shows a transformation the parser applies to text: what happens to whitespace and line breaks in the source text.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close