Markdown Headings: Syntax, Levels, and Best Practices

How to use headings in markdown from H1 to H6. Covers ATX vs Setext syntax, heading IDs, anchor links, and document structure best practices.

· · 6 min read

Last updated: March 3, 2026

markdown headings reference

Headings give structure to a markdown document. They create a hierarchy that helps readers scan content and helps tools generate tables of contents. The syntax is a # prefix: one # for the largest heading, up to six for the smallest.

This guide covers both heading syntaxes, heading IDs for anchor links, and best practices for structuring documents.

ATX-Style Headings

ATX headings use # symbols. The number of hashes determines the level:

# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6

Always put a space between the # and the heading text. Some parsers require it, and it improves readability.

You can optionally add closing hashes for visual symmetry, but they are ignored by the renderer:

## Heading 2 ##
### Heading 3 ###

Setext-Style Headings

Setext headings use underlines for H1 and H2 only:

Heading 1
=========
Heading 2
---------

The underline needs at least one character, but convention is to match the heading length. Setext only covers two levels, so you need ATX syntax for H3 through H6.

Most people use ATX exclusively because it is consistent across all six levels.

Most markdown renderers auto-generate an ID for each heading. The ID is derived from the heading text: lowercased, spaces replaced with hyphens, punctuation stripped.

## Getting Started

Generates id="getting-started", which you can link to:

[Jump to Getting Started](#getting-started)

This is how table-of-contents links work in README files and documentation. For more on linking, see the markdown links guide.

ID Generation by Platform

PlatformRulesExample: ## What's New?
GitHubLowercase, hyphens for spaces, strip most punctuation#whats-new
GitLabSame as GitHub#whats-new
VS CodeLowercase, hyphens for spaces#whats-new
ObsidianLowercase, hyphens for spaces, keeps some chars#what's-new?
MDtoLinkLowercase, hyphens for spaces, strip punctuation#whats-new

Duplicate Headings

If your document has two headings with the same text, most platforms append a suffix:

## Features
## Features

GitHub generates #features and #features-1. Other platforms may use different numbering schemes.

Document Structure Best Practices

Use one H1 per document. The H1 is the document title. In blog posts and README files, this is often set by the frontmatter title field rather than a markdown heading. If your platform injects the title, start your content at H2.

Follow a logical hierarchy. Do not skip levels. Going from H2 to H4 without an H3 in between confuses screen readers and breaks the outline:

<!-- Bad: skips H3 -->
## Section
#### Subsection
<!-- Good: proper hierarchy -->
## Section
### Subsection

Keep headings descriptive. A heading like “Overview” says nothing. “How the API Handles Authentication” tells the reader what to expect.

Do not use headings for styling. If you want big bold text, use bold text. Headings are structural, not visual.

Headings in HTML Output

Markdown headings map directly to HTML heading elements:

MarkdownHTML
# Heading<h1>Heading</h1>
## Heading<h2>Heading</h2>
### Heading<h3>Heading</h3>
#### Heading<h4>Heading</h4>
##### Heading<h5>Heading</h5>
###### Heading<h6>Heading</h6>

Search engines use heading tags to understand page structure. An <h1> signals the main topic, <h2> marks major sections, and <h3> marks subsections. Using headings correctly helps both human readers and search crawlers.

Headings with Other Formatting

You can use inline formatting inside headings:

## A **bold** word in the heading
## An `inline code` heading
## A [linked heading](https://example.com)

Avoid overloading headings with formatting. A heading with bold, italic, code, and a link becomes hard to read. Keep headings clean and direct.

Platform Differences

FeatureGitHubVS CodeObsidianMDtoLinkCommonMark
ATX headings (#)YesYesYesYesYes
Setext headings (===)YesYesYesYesYes
Auto-generated IDsYesYesYesYesParser-dependent
Closing hashes (## Title ##)YesYesYesYesYes
Inline formatting in headingsYesYesYesYesYes
Custom heading IDsNoNoNoNoSome parsers (Kramdown)
Collapsible sections under headingsNo (use <details>)NoYes (folding)NoNo

Common Mistakes

Missing space after #. Without a space, most parsers treat the line as plain text:

<!-- Not a heading -->
#Missing space
<!-- Heading -->
# With space

Using too many heading levels. Most documents only need H1 through H3. If you are reaching H5 or H6, the document may need to be split into separate pages.

Starting every section with the same heading. A document with five ## Overview sections is confusing. Give each section a unique, descriptive heading.

Copy-Paste Templates

Standard document structure:

# Document Title
## Introduction
## Section One
### Subsection
## Section Two
## Conclusion

README structure:

# Project Name
## Installation
## Usage
## Configuration
## Contributing
## License

API documentation:

# API Reference
## Authentication
## Endpoints
### GET /users
### POST /users
## Error Codes

FAQ

How many heading levels does markdown support?

Markdown supports six levels, from # (H1) through ###### (H6). Most documents only use three or four levels.

Should I use ATX or Setext headings?

Use ATX (the # syntax). It works for all six levels and is the dominant convention across platforms. Setext only covers H1 and H2.

Use an anchor link: [text](#heading-id). The heading ID is the heading text lowercased with spaces replaced by hyphens and punctuation removed. For “Getting Started”, the ID is #getting-started.

How do I add a table of contents in markdown?

Create a list of anchor links at the top of your document. There is no automatic TOC syntax in standard markdown, but GitHub generates one on repo pages, and many editors (VS Code, Obsidian) have TOC plugins.

Try It Out

Practice heading structure in the MDtoLink editor and preview your document hierarchy in real time. Publish it to a shareable URL when you’re done.

See all markdown syntax in the markdown cheat sheet.


David Schemm
David Schemm

Founder, MDtoLink

David builds developer tools and writes about markdown workflows, documentation, and AI-assisted publishing.

Publish your markdown to a shareable URL

One command. Free to start. No credit card.