Headings are the skeleton of a document. In Markdown they take one character: # at the start of a line, repeated once per level. Everything else about them — the structure they imply, the table of contents they generate, the anchor links they create — comes free once you get the levels right.

Change the number of # below and watch the sizes shift:

Headings — add or remove a #
Markdown
# The document title

Some introductory text.

## A major section

### A subsection

#### A minor point

Text under a heading belongs to it.
Preview

The document title

Some introductory text.

A major section
A subsection
A minor point

Text under a heading belongs to it.

The six levels

# through ###### map to <h1> through <h6>. There is no level seven; a seventh # renders as literal text.

Markdown
# Heading level 1
## Heading level 2
### Heading level 3
#### Heading level 4
##### Heading level 5
###### Heading level 6
Preview

Heading level 1

Heading level 2
Heading level 3
Heading level 4
Heading level 5
Heading level 6

In practice you will use three. A document that reaches ##### is usually a document that wants to be split in two.

The space is not optional

#Heading is a paragraph starting with a hash. # Heading is a heading. Always put a space after the last #.

This is the single most common reason a heading renders as plain text, and it is invisible until you look at the preview.

One # per document

Use a single # and treat it as the title. Then structure everything below with ## and ###.

Two reasons, and only one of them is about search engines:

  • For readers and screen readers, the heading levels are a navigable outline. Skipping from # to ###, or having three # headings, makes that outline meaningless.
  • For search engines, the <h1> is a strong signal about what the page is about. Several of them dilute it.

Do not skip levels on the way down, either: a ### should sit under a ##, not directly under a #.

Setext headings

There is an older syntax you will meet in files written years ago — underlining the text with = or -:

Markdown
The document title
==================

A major section
---------------
Preview

The document title

A major section

= makes an <h1> and - an <h2>. That is all it can do, which is why it faded: there is no way to express level three. Recognise it when you see it, write # instead.

Beware the trap: a line of dashes directly under a paragraph turns that paragraph into a heading rather than drawing a horizontal rule. If you want a divider, leave a blank line above it.

Most renderers — GitHub, static site generators, documentation tools — give every heading an id derived from its text, so you can link straight to a section:

Markdown
See the [section on anchor links](#headings-become-anchor-links).
Preview

The rule is nearly always the same: lowercase the text, replace spaces with hyphens, drop punctuation. ## The Six Levels becomes #the-six-levels. When two headings share a text, the second usually gets -1 appended.

This is what makes a table of contents possible — including the one on this page. More on linking in the guide to links.

Common mistakes

No space after the #. The line renders as a paragraph. Check this first whenever a heading does not appear.

No blank line around the heading. Some parsers require a blank line before a heading, especially right after a paragraph. Leaving one above and below works everywhere.

Trailing hashes. ## Section ## is legal — the closing hashes are stripped — but it is noise. Leave them off.

Using bold instead of a heading. A line of **Section title** looks like a heading and is not one: it produces no outline entry, no anchor and no structure. Screen readers cannot navigate by it and search engines do not read it as a section.

Several # in one file. Split the document, or demote all but the first.

FAQ

How many heading levels does Markdown support?

Six, from # for <h1> down to ###### for <h6>. A seventh # is not a heading and renders as text. Most documents only need three levels.

Why is my Markdown heading not working?

Almost always a missing space between the # and the text. #Title is a paragraph; # Title is a heading. The second most common cause is the absence of a blank line between the previous paragraph and the heading.

Should a Markdown document have only one H1?

Yes, as a rule. One # acts as the document title and everything else nests below it with ## and ###. It keeps the outline meaningful for screen readers and keeps the page’s main topic unambiguous for search engines.

Use the heading’s generated anchor: lowercase the text, replace spaces with hyphens and remove punctuation, then link to it with #. ## Getting Started becomes [jump](#getting-started). The exact rule varies slightly between renderers.

What is the difference between # headings and underlined headings?

They produce the same result for the first two levels. = under a line makes an <h1> and - makes an <h2>; this older Setext style cannot express levels three to six, so the # syntax has replaced it almost everywhere.