Markdown Links: Inline, Reference, and Relative Syntax
Master Markdown links: inline, reference-style, relative paths, and anchor links to headings, with copy-paste examples and common pitfalls.

A Markdown link is written as [link text](https://example.com): the visible text goes in square brackets, the URL goes in the parentheses right after. That one line covers most of what you need, but Markdown also gives you reference-style links, relative paths for repos, and anchor links that jump to a heading. Here is each form with copy-paste examples and the mistakes that trip people up.
Inline link syntax and how it renders
The inline link is the default answer to “how to add a link in Markdown.” Text in brackets, URL in parentheses, no space between the two pairs:
Read the [Astro docs](https://docs.astro.build) for routing.
That renders as a clickable “Astro docs” pointing to the URL. The bracket text is what the reader sees. The parenthesis part is the destination and never shows on the page.
A few rules the parser cares about. Do not put a space between ] and (, or it stops being a link and prints the literal characters. The URL can be absolute (https://...), relative (/blog/post), or a mailto (mailto:hi@nelenga.com). If your URL itself contains spaces, encode them as %20, because a raw space ends the link early.
You can also nest inline formatting inside the text. [**bold link**](/pricing) makes the visible text bold and still links. That works because Markdown processes the bracket contents as normal inline text.
Reference-style links and when to use them
Reference links split the link into two parts: a label where the link appears, and the URL defined somewhere else in the document. They keep long paragraphs readable when you have many links or one URL you reuse.
We build [tools][t] and write about [Markdown][md].
[t]: https://nelenga.com/tools
[md]: https://www.markdownguide.org
The [t] and [md] are labels, not URLs. At the bottom (or anywhere in the file), you define each label once. Labels are case-insensitive and can be any string. You can even drop the second bracket entirely and let the visible text double as the label:
See the [Markdown Guide].
[Markdown Guide]: https://www.markdownguide.org
Reference-style shines in two cases. First, when the same URL appears several times, you define it once and reference it everywhere, so a URL change is a one-line edit. Second, in prose-heavy writing where inline URLs would clutter the sentence, the body stays clean and the definitions sit out of the way. The rendered output is identical to an inline link. This is purely a source-readability choice.
Relative links for repos and static sites
Relative links point to another file using a path relative to the current file, with no domain. They are how you cross-link pages inside a GitHub repo, a docs site, or a static build.
See the [install guide](./docs/install.md) and the [changelog](../CHANGELOG.md).
./ means the current directory, ../ climbs up one level, and a leading / means the site root. In a GitHub README, [license](LICENSE) resolves against the repo path, so the link keeps working whether someone views the repo on github.com or clones it locally. That portability is the whole point: no hardcoded domain to break when the project moves.
On a static site the same idea applies, but the target is a rendered URL, not a source file. If your build turns about.md into /about/, link to /about, not about.md. Mixing the two is the most common broken-link bug on generated sites. Check what your generator outputs and match it.
Linking to a heading or section (anchor links)
A Markdown link to a heading uses # plus the heading slug. Most renderers auto-generate an id for every heading by lowercasing the text, stripping punctuation, and replacing spaces with hyphens.
Jump to [reference links](#reference-style-links-and-when-to-use-them).
So a heading ## Reference-style links and when to use them becomes the anchor #reference-style-links-and-when-to-use-them. To link to a heading on another page, put the path first, then the anchor: [see relative links](/blog/markdown-links-guide#relative-links-for-repos).
Slug rules vary slightly between GitHub, Astro, and other tools, especially around ampersands, emoji, and duplicate headings (GitHub appends -1, -2 to repeats). When an anchor does not jump, view the rendered HTML and copy the actual id the parser produced instead of guessing.
Adding titles and opening links in a new tab
You can add a title (the tooltip that appears on hover) by putting a quoted string after the URL, inside the parentheses:
[Nelenga](https://nelenga.com "Independent product studio")
The text in quotes becomes the title attribute. It is optional and works the same in reference definitions: [t]: https://nelenga.com "Independent product studio".
Plain Markdown has no syntax for opening a link in a new tab. There is no flag for target="_blank". If you need it, you drop to raw HTML, which most Markdown parsers pass through:
<a href="https://nelenga.com" target="_blank" rel="noopener">Nelenga</a>
Add rel="noopener" for security whenever you use target="_blank". Note that some environments (like MDX or sanitized Markdown) restrict inline HTML, so test that the tag survives your pipeline before relying on it.
Automatic URLs and bare link handling
A bare URL is not always clickable. In strict CommonMark, typing https://nelenga.com on its own renders as plain text. To force a clickable link from a raw URL, wrap it in angle brackets:
<https://nelenga.com>
That is the autolink syntax, and it also works for email: <hi@nelenga.com>. Many popular flavors, including GitHub Flavored Markdown, add “autolink extensions” that turn a bare https:// URL into a link automatically, no brackets needed. That is a GFM feature, not core Markdown, so a URL that links on GitHub may stay plain text elsewhere. When you want a guaranteed link, use the angle-bracket form or a full [text](url).
Common mistakes: broken brackets, encoded spaces
Most broken Markdown links come from a handful of small errors:
- A space between
]and(.[text] (url)prints literally. Close them tight:[text](url). - Unencoded spaces in the URL.
](/my file.pdf)breaks at the space. Use](/my%20file.pdf). - Unbalanced or nested brackets in the text. Link text containing a raw
[or]confuses the parser. Escape them with a backslash:\[. - Reference label defined but never used, or a typo between label and definition. The link silently renders as plain bracketed text. Search for the label to confirm it matches.
- Wrong relative depth. One too few
../and the link 404s. Count directory levels from the current file, not from the site root.
When you paste tabular data (a spreadsheet or CSV) into a doc and it comes out as a wall of text with broken pipes and links, converting it cleanly by hand is painful. Our CSV to Markdown converter turns a CSV into a proper Markdown table in one paste, so you can drop it straight into your README or blog post without hand-fixing every row.
FAQ
How do you add a link in Markdown?
Write [link text](https://example.com). The bracketed text is what readers click, and the URL in parentheses is where it goes. Keep the ] and ( touching, with no space between them.
What is the difference between inline and reference links?
They render identically. An inline link keeps the URL in the sentence: [text](url). A reference link uses a label there and defines the URL elsewhere: [text][label] plus [label]: url. Reference style keeps long paragraphs readable and lets you reuse one URL in several places.
How do you link to a specific heading in Markdown?
Use # and the heading slug: [jump](#my-heading). The slug is the heading text lowercased with spaces turned into hyphens and punctuation removed. For a heading on another page, prefix the path: [jump](/page#my-heading).
Can you open a Markdown link in a new tab?
Not with plain Markdown syntax. There is no built-in flag for it. Use raw HTML instead: <a href="url" target="_blank" rel="noopener">text</a>, and confirm your parser allows inline HTML first.