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.
Last updated: March 3, 2026
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 6Always 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.
Heading IDs and Anchor Links
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 StartedGenerates 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
| Platform | Rules | Example: ## What's New? |
|---|---|---|
| GitHub | Lowercase, hyphens for spaces, strip most punctuation | #whats-new |
| GitLab | Same as GitHub | #whats-new |
| VS Code | Lowercase, hyphens for spaces | #whats-new |
| Obsidian | Lowercase, hyphens for spaces, keeps some chars | #what's-new? |
| MDtoLink | Lowercase, 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## FeaturesGitHub 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### SubsectionKeep 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:
| Markdown | HTML |
|---|---|
# 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
| Feature | GitHub | VS Code | Obsidian | MDtoLink | CommonMark |
|---|---|---|---|---|---|
ATX headings (#) | Yes | Yes | Yes | Yes | Yes |
Setext headings (===) | Yes | Yes | Yes | Yes | Yes |
| Auto-generated IDs | Yes | Yes | Yes | Yes | Parser-dependent |
Closing hashes (## Title ##) | Yes | Yes | Yes | Yes | Yes |
| Inline formatting in headings | Yes | Yes | Yes | Yes | Yes |
| Custom heading IDs | No | No | No | No | Some parsers (Kramdown) |
| Collapsible sections under headings | No (use <details>) | No | Yes (folding) | No | No |
Common Mistakes
Missing space after #. Without a space, most parsers treat the line as plain text:
<!-- Not a heading -->#Missing space
<!-- Heading --># With spaceUsing 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
## ConclusionREADME structure:
# Project Name
## Installation
## Usage
## Configuration
## Contributing
## LicenseAPI documentation:
# API Reference
## Authentication
## Endpoints
### GET /users
### POST /users
## Error CodesFAQ
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.
How do I link to a heading on the same page?
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.
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.