Advanced Markdown Features
Reviewed & published by Brayan K
By the end of this lesson you'll write GitHub-Flavoured Markdown like a maintainer: footnotes, collapsible sections, escaped characters, raw HTML, anchor-link tables of contents, badges, emoji, and highlighted code — everything a polished README needs.
Part of the free Markdown course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn
- Add footnotes with [^label] and match references to definitions
- Embed raw HTML (centring, <kbd>, <span style>) inside Markdown
- Escape special characters with \ to show literal symbols
- Build collapsible sections with <details> and <summary>
- Create a table of contents with anchor links, and add shields.io badges
- Use emoji shortcodes and language-tagged code fences for highlighting
💡 Real-World Analogy
Basic Markdown is like a label maker: quick, tidy, perfect for everyday text. GitHub-Flavoured Markdown adds a toolbox — a collapsible drawer (<details>), little reference cards stapled to the back (footnotes), status stickers (badges), and the option to drop in a raw HTML part when the label maker can't do the job. You still write plain text, but now you can build documentation that looks hand-crafted.
1. Footnotes
A footnote lets you add a note without cluttering your sentence. You drop a marker like [^1] where the note belongs (the reference), then define it on its own line as [^1]: text (the definition). The label can be a number or a word — what matters is that the reference and definition use the exact same label. When rendered, the marker becomes a small superscript link, and all the notes collect at the bottom of the page.
Markdown was created in 2004[^1] and is now everywhere[^docs].
You can even put a footnote mid-sentence[^tip] like this.
[^1]: The original spec was written by John Gruber.
[^docs]: GitHub, Reddit, and Stack Overflow all use it.
[^tip]: Labels can be words, not just numbers.Markdown was created in 2004[1] and is now everywhere[docs].
You can even put a footnote mid-sentence[tip] like this.
- [1] The original spec was written by John Gruber. ↩
- [docs] GitHub, Reddit, and Stack Overflow all use it. ↩
- [tip] Labels can be words, not just numbers. ↩
2. Embedding Raw HTML
Markdown can't do everything — there's no syntax for centring text or colouring a word. When you hit that wall, you can drop raw HTML straight into your Markdown and most renderers (GitHub included) will honour it. Common uses: <p align="center"> to centre a logo, <kbd> to style keyboard keys, <br> for a manual line break, and <span style="..."> for inline colour.
Markdown is great, but sometimes you need raw HTML.
<p align="center">
<strong>Centred text</strong> — Markdown alone can't do this.
</p>
This text is <span style="color: tomato">tomato-coloured</span>
and this is <kbd>Ctrl</kbd> + <kbd>C</kbd> in a keyboard tag.
<br>
A manual line break above using the <br> tag.Markdown is great, but sometimes you need raw HTML.
Centred text — Markdown alone can't do this.
This text is tomato-coloured and this is Ctrl + C in a keyboard tag.
A manual line break above using the br tag.
3. Escaping Special Characters
Characters like *, _, #, and ` have special meaning in Markdown. To show them literally instead of triggering formatting, put a backslash \ in front. So \*hello\* displays the asterisks instead of turning the word italic. This is the difference between escaping (show the symbol) and literal (the symbol already would have shown) — you only need a backslash when the character would otherwise be interpreted.
Show literal Markdown by escaping with a backslash \\ :
\\*not italic\\* -> *not italic* (the asterisks stay visible)
\\# not a heading -> # not a heading
\\` not code \\` -> ` not code `
1\\. not a list -> 1. not a list
Characters you can escape: \\ \` * _ {} [] () # + - . ! |Show literal Markdown by escaping with a backslash \ :
*not italic* (the asterisks stay visible)
1. not a list
4. Collapsible Sections
A collapsible section hides content behind a clickable label — perfect for long FAQs, solutions, or stack traces. It's raw HTML: wrap the content in <details>, and put the always-visible label in <summary>. The one rule that trips everyone up: leave a blank line after </summary> if you want Markdown (lists, code, bold) to render inside.
## Troubleshooting
<details>
<summary>Why won't my footnote render?</summary>
The label after `[^` must match **exactly** between the
reference and the definition. `[^1]` needs `[^1]:` — not `[^one]:`.
You can use **Markdown** inside a collapsed section, including
lists and `code`.
</details>The label after [^ must match exactly between the reference and the definition. [^1] needs [^1]: — not [^one]:.
You can use Markdown inside a collapsed section, including lists and code.
↑ Click the triangle to expand it.
🎯 Your Turn #1: a collapsible FAQ
Fill in the two blanks so the program prints a valid <details> block, then run it. Notice the blank line that lets Markdown render inside.
// 🎯 YOUR TURN — build a collapsible FAQ section.
// Fill in each ___ then press "Try it Yourself" to print your Markdown.
const summaryText = "___"; // 👉 the always-visible label, e.g. "Show the answer"
const hiddenText = "___"; // 👉 the text revealed when expanded
console.log("<details>");
console.log("<summary>" + summaryText + "</summary>");
console.log(""); // blank line is REQUIRED for Markdown inside
console.log(hiddenText);
console.log("");
console.log("</details>");
// ✅ Expected printed source (example):
// <details>
// <summary>Show the answer</summary>
//
// The answer is 42.
//
// </details>
//
// Paste it into GitHub: you'll see a clickable triangle that expands.5. A Table of Contents with Anchor Links
Every heading on GitHub automatically gets an invisible anchor (a link target). You can link to it with [Text](#heading). To work out the anchor: take the heading text, make it lowercase, replace spaces with hyphens, and drop punctuation. So ## FAQ & Support becomes #faq--support (the & is dropped, leaving a double hyphen where the spaces were). String these links into a bullet list and you have a clickable table of contents.
# Project Handbook
## Table of Contents
- [Installation](#installation)
- [Usage](#usage)
- [FAQ & Support](#faq--support)
## Installation
...
## Usage
...
## FAQ & Support
...- Installation
- FAQ & Support
Each bullet jumps to the matching heading further down the page.
6. Badges (shields.io)
Those little status pills at the top of READMEs — build passing, MIT license, version 2.1.0 — are just images. shields.io generates them from a URL, and you embed each one with normal image syntax . The static pattern is .../badge/LABEL-MESSAGE-COLOR.
# Awesome Project




Pattern: https://img.shields.io/badge/LABEL-MESSAGE-COLOR7. Syntax Highlighting & Emoji
A fenced code block (three backticks) becomes syntax-highlighted when you write the language name right after the opening backticks — python, json, bash, diff, and dozens more. And emoji shortcodes like :tada: render as 🎉 — handy for friendly headings and changelogs.
Tell the fence its language for syntax highlighting:
\`\`\`python
def greet(name):
return f"Hello, {name}!"
\`\`\`
\`\`\`json
{ "name": "ada", "active": true }
\`\`\`
\`\`\`diff
+ added this line
- removed this line
\`\`\`Tell the fence its language for syntax highlighting:
:tada: → 🎉 :rocket: → 🚀 :sparkles: → ✨ :bug: → 🐛 :+1: → 👍 :warning: → ⚠️
Here's a worked example that prints real GFM source you can copy. Run it, read each printed line, then paste it into a GitHub README to watch it render.
## Task lists (recap)
- [x] Create repository
- [ ] Write the README
## Footnotes
Markdown is everywhere[^1].
[^1]: Used by GitHub, Reddit, and more.
## Emoji shortcodes
:tada: -> 🎉 :rocket: -> 🚀 :+1: -> 👍
## Badge (shields.io)

Tip: the console prints SOURCE. Paste it into a GitHub
README to see the rendered checkboxes, links, and badges.
<!-- ✅ Expected result, rendered:
h2 -> text: Task lists (recap)
h2 -> count: 4
p -> count: 4
ul -> count: 1
li -> count: 2
img -> count: 1
input[type="checkbox"] -> count: 2
-->🎯 Your Turn #2: a matching footnote
Fill in the blanks so the reference [^label] and the definition [^label]: use the same label. If they don't match, the footnote link breaks — that's the single most common footnote bug.
// 🎯 YOUR TURN — add a footnote. The label in the REFERENCE must match
// the label in the DEFINITION exactly, or GitHub won't link them.
const label = "___"; // 👉 pick a label WITHOUT the ^, e.g. note (used as [^note])
const note = "___"; // 👉 the footnote text shown at the bottom of the page
console.log("Markdown supports footnotes[^" + label + "].");
console.log("");
console.log("[^" + label + "]: " + note);
// ✅ Expected printed source (example, label = "note"):
// Markdown supports footnotes[^note].
//
// [^note]: They appear at the bottom of the rendered page.
//
// If [^note] and [^note]: don't match exactly, the link breaks.One more runnable tour that prints the source for an anchor-link TOC, escaping, raw HTML, and a highlighted fence — all in one place.
## Anchor-link Table of Contents
- [Setup](#setup) // jumps to the '## Setup' heading
- [FAQ & Help](#faq--help)// spaces->-, '&' dropped, lowercased
## Escaping special characters
Type a literal asterisk: \*not italic\*
Type a literal hash: \# not a heading
## Raw HTML inside Markdown
<kbd>Ctrl</kbd> + <kbd>C</kbd> // styled keyboard keys
## Syntax-highlighted code fence
Add the language after the opening backticks, e.g. python, json, diff.
<!-- ✅ Expected result, rendered:
h2 -> text: Anchor-link Table of Contents
h2 -> count: 4
p -> count: 3
ul -> count: 1
li -> count: 2
a -> count: 2
-->Common Errors (and the fix)
- My raw HTML vanished. The renderer stripped it for safety (npm, some blog engines, comment fields sanitise HTML). It's not a syntax error — test on GitHub, where most HTML is allowed.
- My footnote isn't a link. The labels don't match. [^1] in the text must pair with [^1]: in the definition — [^1] and [^one]: won't connect.
- My escape shows the backslash too. You escaped a character that wasn't special, e.g. \a. Only escape Markdown's special characters (\ ` * _ [] () # + - . ! |); everywhere else the backslash stays literal.
- Bold/lists won't render inside my <details>. Add a blank line after </summary>. Without it, the Markdown is treated as raw HTML text.
- My TOC link goes nowhere. The anchor is wrong. Lowercase the heading, swap spaces for hyphens, drop punctuation: ## My Setup! → #my-setup.
📋 Quick Reference — GFM Extras
| Feature | Syntax |
|---|---|
| Footnote | text[^1] … [^1]: note |
| Escape | \* \# \` \| |
| Raw HTML | <kbd>Ctrl</kbd>, <br> |
| Collapsible | <details><summary>…</summary>…</details> |
| Anchor link | [Setup](#setup) |
| Badge |  |
| Emoji | :tada: :rocket: :+1: |
| Task list | - [ ] todo - [x] done |
| Highlighted code | ```python … ``` |
Mini-Challenge: Build a README Section
No blanks this time — just a brief and an outline. Use console.log to print the source for a small README that combines four things you learned: a title, a badge, a collapsible install section, and a highlighted code fence. Run it, then paste the output into a GitHub README to see it render.
// 🎯 MINI-CHALLENGE: print a mini README section
// Build (with console.log) the SOURCE for a small README that includes:
// 1. An H1 title line: # My Tool
// 2. ONE shields.io badge: 
// 3. A collapsible "Install" section using <details>/<summary>
// 4. A fenced \`\`\`bash code block with one install command
//
// ✅ Expected printed source (shape):
// # My Tool
// 
// <details>
// <summary>Install</summary>
//
// \`\`\`bash
// npm install my-tool
// \`\`\`
//
// </details>
// your code herePro Tips
- 💡 Keep HTML minimal. Reach for raw HTML only when Markdown genuinely can't do it (centring, colour, <kbd>) — overusing it makes the source hard to read.
- 💡 Number footnotes loosely. Labels don't have to be in order; [^a], [^note], [^99] all work as long as each reference has a matching definition.
- 💡 Test the anchor. Unsure of an anchor? Hover the rendered heading on GitHub — it shows a 🔗 with the exact #anchor.
- 💡 Collapse noisy content. Long logs, screenshots, and FAQ answers belong in <details> so the README stays scannable.
Frequently Asked Questions
Q: Do footnotes and alerts work everywhere?
No. Footnotes, GitHub alerts, and emoji shortcodes are GFM (or GitHub) extensions. Standard Markdown processors may show [^1] or :tada: as plain text. When in doubt, target GitHub.
Q: Is it safe to put raw HTML in Markdown?
On GitHub, basic structural HTML is fine and common. But scripts and many attributes are stripped, and some platforms remove HTML entirely — so don't rely on it for anything that must always appear.
Q: When do I actually need a backslash?
Only when a special character would otherwise be interpreted — e.g. a literal * at the start of a word, or a # at the start of a line. Inside normal prose those characters usually render fine without escaping.
Q: Why won't Markdown render inside my collapsible section?
You need a blank line after </summary>. With it, GitHub parses the inner content as Markdown; without it, the content is treated as raw HTML.
Lesson Complete — and you've finished the course! 🎉
- ✅ Footnotes link a [^label] reference to a matching [^label]: definition
- ✅ Raw HTML fills Markdown's gaps (centring, <kbd>, colour) — but renderers may strip it
- ✅ A backslash \ escapes special characters so they show literally
- ✅ <details>/<summary> create collapsible sections (blank line for inner Markdown)
- ✅ Anchor links [Text](#heading) build a clickable table of contents
- ✅ shields.io badges, emoji shortcodes, and language-tagged fences polish a README
Where to go next: put it all to work. Write a real README.md for one of your own projects, or revisit the course overview to review earlier lessons. From here, explore a documentation site generator like MkDocs or Docusaurus — they're powered by the exact Markdown you now know. Congratulations on completing the Markdown course! 📝
Practice quiz
How do you place a footnote reference in the text?
- [^1]
- (^1)
- {^1}
- ^^1
Answer: [^1]. A footnote reference looks like [^1], paired with a [^1]: definition.
What must be true for a footnote to link correctly?
- The note must be numbered
- The reference and definition labels must match exactly
- It must be at the top of the file
- It must use HTML
Answer: The reference and definition labels must match exactly. [^1] in the text must pair with [^1]: in the definition; mismatched labels break the link.
Which HTML element creates a collapsible section?
- <collapse>
- <accordion>
- <details> with <summary>
- <toggle>
Answer: <details> with <summary>. <details> wraps the content and <summary> holds the always-visible label.
What is needed after </summary> for Markdown to render inside <details>?
- A semicolon
- A closing tag
- Nothing special
- A blank line
Answer: A blank line. Leave a blank line after </summary> so the inner content is parsed as Markdown.
How do you show a literal asterisk instead of triggering italics?
- Put a backslash before it
- Double it
- Wrap it in quotes
- Use a caret
Answer: Put a backslash before it. A backslash before a special character escapes it so it displays literally.
What does the anchor #faq--support come from?
- A random id
- The heading FAQ & Support lowercased, spaces to hyphens, punctuation dropped
- A manual anchor tag
- The first word only
Answer: The heading FAQ & Support lowercased, spaces to hyphens, punctuation dropped. GitHub lowercases the heading, swaps spaces for hyphens, and drops punctuation like &.
How are shields.io badges embedded in Markdown?
- With a <badge> tag
- With a footnote
- With image syntax 
- With a code fence
Answer: With image syntax . Badges are just images, embedded with .
What does the shortcode :tada: render as?
- A code block
- A link
- Bold text
- The 🎉 emoji
Answer: The 🎉 emoji. Emoji shortcodes like :tada: render as their emoji, here 🎉.
How do you get syntax highlighting in a fenced code block?
- Write the language after the opening backticks
- Add a <code> tag
- Indent four spaces
- Use a footnote label
Answer: Write the language after the opening backticks. Put the language name (python, json, bash) right after the opening three backticks.
Why might raw HTML disappear from your rendered Markdown?
- The syntax is wrong
- The renderer strips or sanitises HTML for safety
- HTML is never allowed
- It needs a footnote
Answer: The renderer strips or sanitises HTML for safety. Some platforms sanitise raw HTML for safety, so it may be removed even when valid.
Continue this course
- Previous: Links and Images
- Next: YAML Front Matter — Add structured metadata with the --- block used by static site generators
- Quick reference: Markdown cheat sheet › Tables & Extras