Markdown
Web Development
HTML
Technical Writing
Documentation

How to link to part of the same document in Markdown?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

To link to another section within the same Markdown document, use the standard link syntax with a # anchor derived from the heading text: [link text](#heading-slug). The slug is created by converting the heading to lowercase, replacing spaces with hyphens, and removing special characters. This is the foundation of every Table of Contents in Markdown and works across GitHub, GitLab, VS Code previews, and most static site generators.

Basic Syntax

Every heading in a Markdown document automatically becomes an anchor target. You link to it by constructing a slug from the heading text.

markdown
1## Table of Contents
2- [Installation](#installation)
3- [Configuration Options](#configuration-options)
4- [API Reference](#api-reference)
5- [Troubleshooting](#troubleshooting)
6
7## Installation
8Steps to install the tool...
9
10## Configuration Options
11How to configure the tool...
12
13## API Reference
14Endpoint documentation...
15
16## Troubleshooting
17Common issues and fixes...

The anchor #configuration-options is derived from the heading ## Configuration Options by lowercasing and replacing the space with a hyphen.

Slug Generation Rules

The exact rules vary slightly between Markdown processors, but the most common convention (used by GitHub, GitLab, and most static site generators) is:

  1. Convert the heading text to lowercase
  2. Replace spaces with hyphens (-)
  3. Remove all punctuation except hyphens
  4. Collapse multiple consecutive hyphens into one
markdown
1## Heading Text                    -> #heading-text
2## What's New in v2.0?             -> #whats-new-in-v20
3## C++ Template Metaprogramming    -> #c-template-metaprogramming
4## Step 1: Install Dependencies    -> #step-1-install-dependencies
5## Don't Repeat Yourself (DRY)     -> #dont-repeat-yourself-dry

Processor-Specific Differences

Not all processors follow the same rules. Here is how common platforms handle edge cases:

PlatformPunctuation handlingDuplicate headingsEmoji in headings
GitHub Flavored MarkdownRemoves most punctuation, keeps hyphensAppends -1, -2, etc.Strips emoji
GitLabSame as GitHubAppends -1, -2, etc.Strips emoji
Hugo (Goldmark)Removes punctuation, keeps hyphensAppends -1, -2, etc.Strips emoji
DocusaurusRemoves punctuationAppends -1, -2, etc.Strips emoji
PandocRemoves punctuation, prefix with section- optionalAppends -1, -2, etc.Keeps emoji in ID
VS Code previewFollows CommonMark extensionsDoes not deduplicateStrips emoji

When in doubt, check the rendered HTML and inspect the id attribute on the heading element.

Manual Anchors with HTML

When the auto-generated slug is inconvenient or you need an anchor at a location other than a heading, you can insert a raw HTML anchor.

markdown
1## Using HTML Anchors
2
3You can place an anchor anywhere in the document:
4
5<a id="custom-anchor"></a>
6
7This paragraph is the target of the custom anchor.
8
9Link to it from anywhere: [Jump to custom section](#custom-anchor)

This is particularly useful for:

  • Linking to a specific paragraph, not just a heading
  • Creating short, stable anchor names that do not change when you rename a heading
  • Linking to positions inside code blocks or tables

Some Markdown processors also support the heading ID syntax with curly braces:

markdown
## My Long Heading Title {#short-id}

[Link to it](#short-id)

This works in Pandoc, Hugo, Docusaurus, and several other processors, but not in GitHub Flavored Markdown.

Building a Table of Contents

A manual table of contents is just a list of internal links at the top of the document.

markdown
1# Project README
2
3## Table of Contents
41. [Overview](#overview)
52. [Prerequisites](#prerequisites)
63. [Installation](#installation)
7   - [macOS](#macos)
8   - [Linux](#linux)
9   - [Windows](#windows)
104. [Usage](#usage)
115. [Contributing](#contributing)
12
13---
14
15## Overview
16Brief description of the project...
17
18## Prerequisites
19What you need before installing...
20
21## Installation
22
23### macOS
24```brew install mypackage```
25
26### Linux
27```sudo apt install mypackage```
28
29### Windows
30Download the installer from...
31
32## Usage
33How to use the tool...
34
35## Contributing
36How to contribute to the project...

Many tools can auto-generate a TOC. For example, VS Code has Markdown All in One extension, and many static site generators have TOC plugins. But the manual approach gives you full control over ordering and nesting.

Linking Across Files

While not strictly "same-document" linking, you can combine file paths with anchors to link to specific sections in other Markdown files.

markdown
1<!-- Link to a heading in another file -->
2See the [authentication section](./docs/security.md#authentication)
3
4<!-- Relative path from a nested directory -->
5Refer to the [API docs](../api/endpoints.md#post-users)

On GitHub, these links work in repository browsing. In static site generators, the file extension is usually replaced with .html or removed entirely depending on the URL scheme.

Practical Example: A Full Document

markdown
1# Deployment Guide
2
3## Table of Contents
4- [Prerequisites](#prerequisites)
5- [Environment Setup](#environment-setup)
6- [Database Migration](#database-migration)
7- [Rolling Deployment](#rolling-deployment)
8- [Rollback Procedure](#rollback-procedure)
9- [Health Checks](#health-checks)
10
11## Prerequisites
12
13Ensure you have:
14- Docker 24+
15- kubectl configured for the target cluster
16- Access to the container registry
17
18For registry setup, see [Environment Setup](#environment-setup).
19
20## Environment Setup
21
22Export the required variables:
23...
24
25## Database Migration
26
27Run migrations **before** deploying new code.
28If migration fails, see [Rollback Procedure](#rollback-procedure).
29
30## Rolling Deployment
31
32The deployment uses a rolling update strategy.
33After deployment, verify with [Health Checks](#health-checks).
34
35## Rollback Procedure
36
37To roll back, redeploy the previous image tag.
38Check [Prerequisites](#prerequisites) for required access.
39
40## Health Checks
41
42Verify that `/healthz` returns 200 on all pods.

Notice how the internal links create a navigable web within a single document, letting readers jump directly to relevant sections.

Common Pitfalls

  • Forgetting to lowercase the anchor. Markdown anchors are case-insensitive in some processors but case-sensitive in others. Always use lowercase in your links to be safe: [Link](#my-heading), not [Link](#My-Heading).
  • Including punctuation in the anchor. A heading like ## What's New? becomes #whats-new, not #what's-new?. Apostrophes, question marks, periods, and colons are stripped.
  • Duplicate headings. If you have two ## Overview headings, the second one becomes #overview-1. This is fragile because inserting a new heading can shift the numbering. Use unique heading text or manual anchors.
  • Spaces in anchors. Anchors use hyphens, not spaces or %20. Writing [Link](#my heading) will not work.
  • Relying on curly-brace IDs on GitHub. The {#custom-id} syntax is not supported on GitHub. Use <a id="custom-id"></a> instead if you need custom anchors on GitHub.
  • Not testing links after renaming headings. When you rename a heading, every internal link pointing to it breaks silently. Search your document for the old anchor text after any heading change.

Summary

Internal links in Markdown use the syntax [text](#anchor) where the anchor is derived from the heading text by lowercasing, replacing spaces with hyphens, and stripping punctuation. For custom anchor positions, use <a id="name"></a> in HTML. For processors that support it, the {#id} attribute syntax provides cleaner custom anchors. Always verify your slugs match the processor's rules, keep headings unique to avoid numbered suffixes, and search for stale anchors whenever you rename a heading. These links are the backbone of readable, navigable documentation.


Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.