Headings

Headings are the skeleton of a document. They decide how the content is chunked, how an automatic table of contents is generated, and whether a reader can find their way through a long page in seconds. Markdown offers only two ways to write a heading, but both come with details that are easy to miss: a heading needs a space after its hashes, a heading may contain inline formatting but nothing else, and the row of dashes that people reach for as a separator is also a heading underline in disguise.

After this page you should be able to write all six levels in either style, explain why the levels of a document should never skip, and look at a heading that failed to render and immediately name the rule it broke.

Syntax

The style almost everyone meets first is called ATX, after the original “ATX headings” section of the Markdown syntax description. The number of hashes sets the level, from one hash for level 1 down to six hashes for level 6:

# Level 1 heading
## Level 2 heading
### Level 3 heading

After parsing, that source becomes exactly three heading elements:

<h1>Level 1 heading</h1>
<h2>Level 2 heading</h2>
<h3>Level 3 heading</h3>

The space after the hashes is part of the syntax, not decoration. The parser looks for a run of hashes followed by a space, so #Heading is just a word that happens to start with a hash, and ####### is not a deeper heading but ordinary text: there are only six levels. A heading may also be closed with a second run of hashes, which lets the text contain a hash of its own, so ## C# and F# ## parses as a level 2 heading reading C# and F#.

What a heading may contain

A heading holds inline content, which means code spans, emphasis, and links all work inside it:

## This is a `code` heading with **bold** text
<h2>This is a <code>code</code> heading with <strong>bold</strong> text</h2>

What a heading may not contain is block content. As soon as a list, a code block, or a table appears, the heading is over and the following content starts a new block:

## Configuration

- Database host
- Timeout
<h2>Configuration</h2>
<ul>
<li>Database host</li>
<li>Timeout</li>
</ul>

If you try to keep the list inside the heading, you end up with a heading followed by a separate list. The visual result is very close to what you wanted while the structure is not, and this is the most common reason a heading seems to swallow the section it was supposed to introduce.

The second style: Setext headings

The older style is called Setext. The text goes on its own line and the line below it decides the level: a row of equals signs gives level 1, a row of dashes gives level 2.

Installation Guide
==================

Prerequisites
-------------
<h1>Installation Guide</h1>
<h2>Prerequisites</h2>

Setext is closer to how people used to write plain text documents by hand, and it is fully valid Markdown. The complication is that a row of dashes means two different things depending on what sits above it. After a line of ordinary text it is an underline, so the text becomes a level 2 heading. Directly after an ATX heading it is a horizontal rule instead, because a setext underline only ever applies to a paragraph and an ATX heading is not a paragraph. Standalone, between blank lines, it is a horizontal rule as well:

Some heading text
---

## A heading
---
<h2>Some heading text</h2>
<h2>A heading</h2>
<hr>

Because of that ambiguity, ATX is the safer default for everyday writing. Setext stays useful for a title block at the top of a long document, where the visual weight of an underlined title reads well and where nothing else can be mistaken for it.

Choosing a level

A document should have exactly one level 1 heading: the title of the whole thing. Everything else lives underneath it, and the levels describe a hierarchy rather than an order of appearance.

  • Start at level 1 and move down one level at a time; never jump straight to level 4 or 5.
  • Keep the meaning of a level consistent across the document, so a table of contents and a search index both stay useful.
  • Give every section a heading, so that a reader can skim the outline instead of reading linearly.

These are not stylistic preferences. A generated table of contents is built directly from the heading tree, so a skipped level produces a visibly broken tree in the sidebar. Putting two unrelated topics under the same heading makes their anchor links and search results indistinguishable, which quietly breaks every cross-reference pointing at them. A heading that can stand on its own as a sentence is worth far more than any debate about how many hashes to use.

Common pitfalls

SourceWhat rendersWhy
#Heading (no space after the hash)ordinary paragraphATX requires a space after the hashes
####### Seven hashesordinary paragraphonly levels 1 to 6 exist
## A heading followed by ---level 2 heading plus a horizontal rulea setext underline applies to paragraphs, not to ATX headings
Some text followed by ---level 2 headingthe setext underline wins over the horizontal rule reading
a heading followed by a listthe list becomes its own blocka heading can only hold inline content
## Heading ## followed by more wordsthe closing hashes stay in the textthe closing run must be alone on the line

Exercises

You are writing a deployment guide. The document is called “Deployment Guide” and it has three sections: “Prerequisites”, “Install Dependencies”, and “Start the Service”. Write the heading structure for this document in ATX style, and state which level each heading should use.

Heading hierarchyDocument structureATX headings

Approach:

Heading levels express ownership, not order. The document title is the top of the tree, so it takes level 1. The three sections are siblings underneath it, so they take level 2. Level 3 is reserved for material nested inside one of those sections, such as the individual install commands.

Steps:

  1. Give the document title the level 1 heading.
  2. Give the three sections level 2 headings, keeping them siblings at the same level.
  3. Use level 3 only for subsections that really live inside one of the three sections, and check that the outline reads # then three ## entries with no level skipped.

Answer:

# Deployment Guide

## Prerequisites

## Install Dependencies

## Start the Service

Summary

You should now be able to write a valid heading at any of the six levels, choose between ATX and Setext on purpose rather than by habit, and recognise the reasons a heading silently turns into a paragraph: a missing space after the hashes, more hashes than there are levels, or a line that does not start with hashes at all. When you outline a long document, list the headings first and fill in the text afterwards, and the structure of the page will already be settled before you write a single sentence.

Found an issue with this content?

Tell us what could be improved.