Lesson 4 • Markdown
Links and Images
By the end of this lesson you'll be able to add clickable links, hover tooltips, reusable reference links, autolinks, and embedded (or clickable) images to any Markdown document — and you'll be able to picture the rendered result before you ever open a previewer.
What You'll Learn
- Write inline links with [text](url) and read the rendered result
- Add a hover tooltip with [text](url "title")
- Reuse one URL many times with reference-style links [text][ref]
- Make bare URLs clickable with autolinks <https://...>
- Embed images with  and write good alt text
- Create clickable images and use relative paths inside a repo
**bold**, headings, and basic Markdown structure. Everything about links and images we'll build from scratch here.💡 Real-World Analogy
A link is a signpost. The words in [square brackets] are what the signpost says — the part readers see and click. The (parentheses) are the direction it points — the URL nobody reads but everybody follows. An image is the exact same signpost with a single ! stamped in front, which tells Markdown: "don't make a clickable label here — actually show the thing at this address." Remember the order — label first [], address second () — and you've learned 90% of this lesson.
1. Inline Links
An inline link puts the destination right next to the text. The shape is always [text](url) with no space between the ] and the (. The text in brackets is what your reader sees and clicks; the URL in parentheses is where they go.
Source → Rendered
MARKDOWN SOURCE
Read the [official docs](https://developer.mozilla.org) today.
RENDERED RESULT
Only the bracketed words become the link — the URL itself is hidden from the reader.
2. Links With a Title (Tooltip)
Add a quoted string after the URL, still inside the parentheses, to give the link a title — the little tooltip that pops up on hover. The shape is [text](url "title"). Mind the space before the quote and that the quotes stay inside the ().
Source → Rendered
MARKDOWN SOURCE
[MDN Docs](https://developer.mozilla.org "Mozilla Developer Network")
RENDERED RESULT (hover over the link)
Hover the link above — your browser shows the title "Mozilla Developer Network".
3. Reference-Style Links
When the same URL appears many times — or you just want your prose to stay readable — use a reference-style link. You write a short label where the link appears, then define that label once anywhere in the document. The shape is [text][label] plus a separate [label]: url line. The definition line never shows up in the rendered output.
Source → Rendered
MARKDOWN SOURCE
Read the [install guide][setup], then the [API docs][api]. [setup]: https://docs.example.com/install [api]: https://docs.example.com/api "API Reference"
RENDERED RESULT
The two [label]: url lines vanish from the output — they only tell Markdown where each label points. Labels are case-insensitive and can be reused as many times as you like.
4. Autolinks
If you just want a raw URL to become clickable with no separate label, wrap it in angle brackets: <https://...>. The URL becomes both the link text and the destination. This also works for email addresses, e.g. <you@example.com>.
Source → Rendered
MARKDOWN SOURCE
Status page: <https://status.example.com> Contact: <help@example.com>
RENDERED RESULT
Without the angle brackets, many parsers leave a bare URL as plain, unclickable text.
Here's all four link styles in one runnable example. Read every comment, run it, and confirm the printed Markdown matches what you expect.
Worked example: every link style
Read the comments, run it, and study the printed Markdown.
// Markdown LINKS — printed as text so you can study the syntax.
// (Paste any of these into Dillinger.io or a README to see them render.)
console.log("=== Inline link ===");
// Pattern: [visible text](destination-url)
console.log("[Visit Google](https://google.com)");
// renders as: Visit Google (clicking goes to https://google.com)
console.log("=== Inline link WITH a title (hover tooltip) ===");
// Add "..." AFTER the url, inside the parentheses.
console.log('[MDN Docs](https://develo
...Your turn. The program below is almost complete — fill in the three ___ blanks using the 👉 hints, then run it and check the printed lines against the expected output in the comments.
🎯 Your turn: fix the links
Replace each ___ so the printed text is valid Markdown.
// 🎯 YOUR TURN — replace each ___ then press "Try it Yourself".
// These lines PRINT Markdown. Fix them so the printed text is valid Markdown.
// 1) Make an INLINE link: the words "My Portfolio" pointing to https://me.dev
console.log("[My Portfolio]___"); // 👉 replace ___ with (https://me.dev)
// 2) Add a TITLE tooltip "Source code" to a GitHub link:
console.log('[Repo](https://github.com/me/app ___)'); // 👉 replace ___ with "Source code"
// 3) Turn this bare URL into an AUTOLINK (w
...5. Images
An image is a link with one extra character: a leading !. The shape is . The alt text in the brackets is not a label this time — it's the description screen readers announce and the text that shows if the image fails to load. Always write meaningful alt text. You can add a title tooltip exactly like a link: .
Source → Rendered
MARKDOWN SOURCE

RENDERED RESULT
The framed box stands in for the real picture. If the file at puppy.jpg can't load, that alt text — "A golden retriever puppy" — is exactly what readers (and screen readers) get instead.
6. Clickable (Linked) Images
To make an image clickable, put the whole image syntax inside a link's brackets: [](destination). The image is the "text" of the link. This is how README badges work — a status badge image that links to your build pipeline.
Source → Rendered
MARKDOWN SOURCE
[](https://ci.example.com)
RENDERED RESULT (the whole image is a link)
Notice the nesting order: the ![...] image sits in the spot where a link's text would normally go.
7. Relative Links & Paths
URLs starting with https:// are absolute. But inside a project you usually point to files that live alongside your Markdown — that's a relative path, with no https://. ./docs/setup.md means "the setup file in the docs folder next to me"; images/banner.png works the same way for images. Relative paths keep working when you move the whole repo, which is why GitHub READMEs use them.
Source → Rendered
MARKDOWN SOURCE
See the [contributing guide](./CONTRIBUTING.md). 
RENDERED RESULT
Relative links resolve against the file's own location, so the same Markdown works on your machine, on GitHub, and on a docs site.
Here are all the image patterns in one runnable example — basic, titled, clickable, reference-style, and relative.
Worked example: every image pattern
Read the comments, run it, and study the printed Markdown.
// Markdown IMAGES — the ONLY difference from a link is the leading ! mark.
console.log("=== Basic image ===");
// Pattern: 
console.log("");
// renders as: the image, OR the alt text if it fails to load.
console.log("=== Image with a title ===");
console.log('');
// the "..." becomes a tooltip on hover.
console.log("=== Linked (clickable) image ===");
// Put a WHOLE ima
...Your turn again. Fill in the three ___ blanks below — one of them is just adding the missing ! — then run it and check against the expected output.
🎯 Your turn: fix the images
Replace each ___ so the printed text is valid image Markdown.
// 🎯 YOUR TURN — replace each ___ then press "Try it Yourself".
// 1) EMBED an image of a cat. alt text = "Sleepy cat", url = cat.jpg
console.log("___[Sleepy cat](cat.jpg)"); // 👉 a link becomes an image by adding ___
// 2) Make a CLICKABLE image: wrap an image of logo.png in a link to https://acme.dev
console.log("[]___"); // 👉 replace ___ with (https://acme.dev)
// 3) RELATIVE path: embed assets/hero.png with alt text "Hero banner"
console.log("![Hero banner]___")
...Pro Tips
- 💡 Standard Markdown can't resize images. Drop down to HTML when you need a width:
<img src="logo.png" width="200" alt="Logo">works right inside Markdown. - 💡 Encode spaces in URLs. A space breaks the link; write
%20instead —(my%20file.pdf), not(my file.pdf). - 💡 Reference links keep prose readable. If a paragraph has five links, reference style stops the raw URLs from drowning the sentence.
- 💡 Badges are clickable images. Generate them at shields.io and wrap them in a link to the thing they report on.
Common Errors (and the fix)
- Brackets and parentheses swapped:
(text)[url]renders as literal text, not a link. The label always comes first in[ ], the URL second in( )—[text](url). - Forgot the
!on an image:[alt](photo.png)makes a link to the file;shows the image. The bang is what turns a link into an image. - Reference label never defined:
[text][docs]with no matching[docs]: urlline renders as plain bracketed text. Check the label spelling — it's case-insensitive but must match. - A space inside the URL:
[file](my report.pdf)breaks at the space. Encode it:[file](my%20report.pdf), or rename the file to avoid spaces. - A space between
]and(:[text] (url)won't link. Keep them touching:[text](url).
📋 Quick Reference
| Element | Syntax |
|---|---|
| Inline link | [text](url) |
| Link + title | [text](url "title") |
| Reference link | [text][ref] … [ref]: url |
| Autolink | <https://example.com> |
| Image |  |
| Clickable image | [](url) |
| Relative path | ./docs/file.md |
Frequently Asked Questions
Q: What's the real difference between an inline and a reference-style link?
Only where the URL lives. Inline keeps the URL right beside the text; reference style moves it to a separate [label]: url line so your paragraph stays clean. They render identically.
Q: Why won't my image show up — I only see the alt text?
The URL or path is wrong, so the file can't load and the alt text is the fallback. Check for a missing !, a typo in the path, or a relative path pointing at the wrong folder.
Q: Can I resize or centre an image in Markdown?
Not with plain Markdown. Use HTML, which most renderers accept: <img src="x.png" width="300">, and wrap it in <p align="center">…</p> to centre it.
Q: My link has a space in the URL and breaks — what do I do?
Replace each space with %20 (URL encoding), e.g. (report%20final.pdf). Better yet, avoid spaces in filenames altogether.
Mini-Challenge: a README Footer
No blanks this time — just a brief and an outline. Write the console.log calls that print valid Markdown for an inline link, a reference-style link, and a clickable badge image. Run it and compare against the expected output in the comments.
🎯 Mini-Challenge: print a README footer
Combine inline links, a reference link, and a clickable badge image.
// 🎯 MINI-CHALLENGE: a tiny README footer
// Use console.log to PRINT valid Markdown for ALL of the following:
// 1. An inline link: the word "Docs" -> https://docs.acme.dev
// 2. A reference-style link: "Report a bug" using the label [bugs],
// then define [bugs]: https://github.com/acme/app/issues
// 3. A clickable badge image: the image
// https://img.shields.io/badge/build-passing-green linked to
// https://github.com/acme/app/actions
//
// ✅ Expected printed output (order doesn'
...🎉 Lesson Complete!
- ✅ Inline links:
[text](url)— label in[], address in() - ✅ Add a tooltip with
[text](url "title") - ✅ Reuse URLs with reference links
[text][ref]+[ref]: url - ✅ Make bare URLs clickable with autolinks
<https://...> - ✅ Images are links with a leading
!:— always write alt text - ✅ Clickable images
[](url)and relative paths like./docs/file.md - ✅ Next lesson: Advanced Markdown — task lists, footnotes, and GitHub-flavoured Markdown
Sign up for free to track which lessons you've completed and get learning reminders.