Links and Images
Linking and illustrating in Markdown: inline and reference-style links, autolinks, relative links between files, and images with good alternative text.
Inline links
An inline link is the most common
way to link in Markdown: the link text in square brackets,
immediately followed by the destination in parentheses. The renderer
turns it into an HTML
anchor element, <a href="…">, with your text inside.
Planned maintenance is listed on the [Kestrel status page](https://status.example.com).
<p>Planned maintenance is listed on the <a href="https://status.example.com">Kestrel status page</a>.</p>
The link text can contain other inline formatting, such as
emphasis or inline code. The destination can be a full address with a scheme
(https://, mailto:), a path to another
file, or a fragment (#…) that points to a place on the
same page. The sections below cover each of those.
Link titles
A link title is optional extra
text after the destination, inside the parentheses, in double
quotes, single quotes or parentheses. It becomes the
title attribute of the link, which most desktop
browsers show as a small tooltip when you hover over the link.
Follow the [restart runbook](docs/runbook.md "Portal runbook, section 3").
<p>Follow the <a href="docs/runbook.md" title="Portal runbook, section 3">restart runbook</a>.</p>
Use titles sparingly. A tooltip only appears for mouse users: people on a phone or using only a keyboard never see it, and screen readers do not reliably read it. Anything the reader needs belongs in the link text or the sentence around it.
Reference links
A reference link splits a link in two: in the text you write only the link text and a label, and the address is defined once, somewhere else in the document. That definition line is a link reference definition: the label in square brackets, a colon, the destination and an optional title. It is not shown in the output; it only tells the renderer what the label stands for.
During an outage, check the [status page][status] first.
Customers see the same [status page][status] in the [portal][].
[status]: https://status.example.com "Kestrel Energy status"
[portal]: https://portal.example.com
<p>During an outage, check the <a href="https://status.example.com" title="Kestrel Energy status">status page</a> first. Customers see the same <a href="https://status.example.com" title="Kestrel Energy status">status page</a> in the <a href="https://portal.example.com">portal</a>.</p>
There are three forms of reference link:
-
Full:
[status page][status]. Your own link text, then the label. -
Collapsed:
[portal][]. The link text is also the label. -
Shortcut:
[portal]. The same, with the empty brackets left out. Convenient, but square brackets in ordinary text become a link whenever a definition with that label happens to exist.
Labels are case-insensitive: [Status],
[STATUS] and [status] all match the same
definition. The definitions can stand anywhere in the document; most
people collect them at the end of the section or the file, like
footnotes in a printed book.
See the [status page][staus].
[status]: https://status.example.com
<p>See the [status page][staus].</p>
Autolinks and bare URLs
Sometimes the address itself is the link text. An
autolink is an absolute address or
an email address between angle brackets:
<https://status.example.com>. The renderer uses
the address as both the destination and the visible text; an email
address gets mailto: in front, so clicking it opens a
new message.
Questions? Mail <servicedesk@example.com> or see <https://status.example.com>.
<p>Questions? Mail <a href="mailto:servicedesk@example.com">servicedesk@example.com</a> or see <a href="https://status.example.com">https://status.example.com</a>.</p>
An autolink needs a scheme such as https:,
ftp: or mailto: (implied for email
addresses). <www.example.com> has none, so it is
not an autolink; with raw HTML switched off, as here, the angle
brackets simply appear as text.
Bare URLs
In
CommonMark, the specification most renderers follow, an address without
brackets is just text. GitHub Flavored Markdown adds "extended
autolinks": GitHub turns bare https://… addresses,
www. addresses and email addresses into links without
any brackets. markdown-it, the renderer this site uses, has a
linkify option for the same idea. The example below
turns it on (data-md-linkify).
Status: https://status.example.com (also at www.example.com/status)
<p>Status: <a href="https://status.example.com">https://status.example.com</a> (also at www.example.com/status)</p>
Only the address with a scheme became a link. Since version 15 (July
2026), markdown-it's linkify no longer links addresses without a
scheme, such as www.example.com, unless the developer
enables that separately. Other renderers do link them. This is
exactly the kind of difference between
Markdown flavors
that makes the same file look different in two places.
Links between files and headings
Documentation in a repository is usually a set of Markdown files
that link to each other: the README links to the installation guide,
the runbook links to the escalation list. For those links, use a
relative URL, a path from the current file to the other file, instead of a full
https:// address.
Portal README
- [Installing the portal](docs/install.md)
- [Restarting the portal](docs/runbook.md#restart-the-portal)
- [License terms](../LICENSE)
- [Known issues](#known-issues), further down this page
<p>Portal README</p> <ul> <li><a href="docs/install.md">Installing the portal</a></li> <li><a href="docs/runbook.md#restart-the-portal">Restarting the portal</a></li> <li><a href="../LICENSE">License terms</a></li> <li><a href="#known-issues">Known issues</a>, further down this page</li> </ul>
Relative links are better for three reasons. They keep working in every copy of the repository: on a colleague's laptop, in a fork, in a generated documentation site. On GitHub they follow the branch you are looking at: GitHub rewrites a relative link or image path to the branch currently shown, so a link from a feature branch leads to that branch's version of the file. And they survive a rename of the organization or repository. The page Writing Documentation in Markdown covers how to organize the files themselves.
Links to a heading
A link ending in #something points to an element with
that id. Markdown itself gives headings no ids:
CommonMark and markdown-it's default output contain plain
<h2> elements. Platforms such as GitHub and
GitLab, and most documentation tools, add an id to every heading,
made from its text: "Restart the portal" becomes
#restart-the-portal. The exact rules differ per
platform; see
Markdown on GitHub and GitLab. A heading link that works on GitHub can therefore do nothing in
another renderer, and renaming a heading breaks every link to it.
Images
An image in Markdown is
written like an inline link with an exclamation mark in front:
. Instead of a link,
the renderer produces an HTML <img> element: the
text in the brackets becomes the alt attribute, the
path becomes src.
The outage of 3 March affected two areas in Rotterdam-North:

<p>The outage of 3 March affected two areas in Rotterdam-North:</p> <p><img src="images/outage-2026-03-03.png" alt="Outage map: two areas affected in Rotterdam-North" title="Outage map, 3 March 2026"></p>
The image file does not exist next to this page, so the result frame shows what a reader sees when an image fails to load: a broken-image marker and the alt text. That is one reason the alt text matters (more in the next section).
Images also come in reference form, ![alt][label], with
the same definitions as reference links. And because an image is
inline content, it can be the text of a link: this is how the small
status "badges" at the top of many READMEs are made.
[](https://ci.example.com/portal)
<p><a href="https://ci.example.com/portal"><img src="https://ci.example.com/portal/badge.svg" alt="Build: passing"></a></p>
Writing good alt text
The alternative text (alt text) is what a screen reader reads aloud instead of the image, what a browser shows when the image does not load, and what search engines index. GitHub's own guidance describes it as a short text equivalent of the information in the image. A few practical rules:
- Describe the information, not the file. "Outage map: two areas affected in Rotterdam-North" says what the image is for; "map.png" or "screenshot" says nothing.
- Screenshots of text: put the important text in the alt text or, better, in the document itself. An error message in a screenshot cannot be searched or copied.
- Diagrams: summarize what the diagram shows in a sentence or two, and explain the details in the text around it.
-
Decorative images, such as a divider or a logo
repeated next to the project name: leave the brackets empty,
. The renderer writesalt="", which tells screen readers to skip the image. A raw HTML<img>without anyaltattribute is not the same: screen readers may then read out the file name.
The alt text is plain text. You can type formatting inside the brackets, but the renderer strips it, as the example shows:

<p><img src="images/meter-cupboard.jpg" alt="Meter cupboard with the gas meter on the left"></p>
Descriptive link text
Screen reader users often jump from link to link or ask for a list of all links on a page. In that list, "click here", "here" and "this link" are meaningless. Sighted readers scan for links too: the underlined words are what the eye lands on. Let the link text say where the link goes.
For the escalation list, click [here](docs/escalation.md).
See the [escalation list for the NOC](docs/escalation.md).
<p>For the escalation list, click <a href="docs/escalation.md">here</a>.</p> <p>See the <a href="docs/escalation.md">escalation list for the NOC</a>.</p>
The second version also reads better in the plain-text file. The same advice holds in HTML (see link text), and markdownlint's rule MD059 flags generic link texts.
Traps that break links
Markdown never reports an error. When a link is not valid, the renderer quietly shows the characters as text. These are the usual causes:
-
A space between
]and(.[Status page] (https://…)is not a link. -
Spaces in the destination. Write a space as
%20(see percent-encoding), or put the whole destination in angle brackets; the renderer then encodes the space for you. -
Unbalanced parentheses in the address. Balanced
pairs, as in many wiki addresses, work; a single
(or)ends the link early or breaks it. Use%28and%29, or angle brackets.
[Status page] (https://status.example.com)
[Runbook](docs/portal runbook.md) and [Runbook](<docs/portal runbook.md>)
<p>[Status page] (https://status.example.com)</p> <p>[Runbook](docs/portal runbook.md) and <a href="docs/portal%20runbook.md">Runbook</a></p>
Only the last link survived, with the space encoded as
%20. A file name without spaces
(portal-runbook.md) avoids the problem altogether.
Links that renderers refuse
A link destination can also be a javascript: address,
which would run code when someone clicks it. Careful renderers
refuse such addresses. markdown-it, with its default settings, does
not create a link for javascript:,
vbscript:, file: and most
data: addresses and leaves the text as it was:
[Open the report](javascript:alert('hello'))
<p>[Open the report](javascript:alert('hello'))</p>
Not every renderer does this by default. If your application turns Markdown from users into HTML, read HTML in Markdown and Safety before you publish it.