---
title: "Markdown syntax guide: every common element, with source and result"
slug: markdown-syntax-guide
excerpt: A plain reference to Markdown syntax. Each element shows the source you type and the result you get, from headings and lists to tables, task lists and code blocks.
quickAnswer: "Markdown is a way to format plain text with a few symbols. A # starts a heading, * or _ marks emphasis, - starts a list item, and [text](url) makes a link. Backticks mark code, > starts a quote, and pipes build a table. A renderer turns these symbols into a formatted page. The core rules come from the CommonMark spec. GFM, a widely used superset, adds tables, task lists, strikethrough and bare-URL links."
keyTakeaways:
  - Markdown is plain text with a few symbols. The file reads fine raw and looks formatted once a renderer shows it.
  - CommonMark defines the core syntax. GFM adds tables, task lists, strikethrough and bare-URL links on top.
  - Blank lines matter. They separate paragraphs, lists and blocks, and a missing one can change how a page renders.
  - Tables, task lists and strikethrough only render in tools that support GFM. Elsewhere you see the raw symbols.
  - When something renders wrong, look at the raw text first. The fix is often a space, a blank line or an escape.
publishedDate: 2026-10-06
dateModified: 2026-10-06
author: Bobby Huang
cluster: B
role: pillar
status: published
faq:
  - q: What is the difference between CommonMark and GFM?
    a: CommonMark is a precise spec for core Markdown, such as headings, lists, links, code and quotes. GFM is a superset of CommonMark. It adds tables, task lists, strikethrough, links from bare URLs, and a filter that blocks a few unsafe HTML tags.
  - q: How do you make a table in Markdown?
    a: Write a header row with cells split by pipes, then a row of dashes under it, then one row per line of data. Colons in the dash row set the alignment. Tables are a GFM feature, so they need a renderer that supports GFM.
  - q: How do check boxes work in Markdown?
    a: Start a list item with "- [ ]" for an open box or "- [x]" for a ticked one. A GFM renderer shows real check boxes. Other tools show the brackets as text.
  - q: How do I add an image by relative path?
    a: Write ![alt text](images/diagram.png). Most viewers read the path from the folder the Markdown file sits in. The Markdown spec leaves that to the viewer. Keep the image next to the file or in a subfolder, and use forward slashes.
  - q: Why does my Markdown look different in two apps?
    a: Each app uses its own renderer and its own set of extensions. Core syntax renders the same almost everywhere. Tables, task lists, footnotes, math and diagrams depend on the app.
related:
  - what-is-a-md-file
  - markdown-task-lists
  - how-to-review-markdown-your-ai-agents-write
---

Markdown is a way to write formatted text with plain characters. You type a few symbols, and a renderer turns them into headings, lists, links and tables. The file stays readable even when nothing renders it.

This guide covers the elements you will meet most often. Each one shows the **source** you type. Most also show the **result**, or say what it looks like. Where an element only works in some tools, the guide says so.

## How Markdown works in one minute

A Markdown file is a plain text file, usually saved with a `.md` extension. If that part is new, start with [what a .md file is](what-is-a-md-file.md).

Two specs define most of the syntax:

- **CommonMark** is a precise spec for the core: headings, paragraphs, emphasis, lists, links, images, code, quotes and rules.
- **GFM** is a superset of CommonMark. It adds tables, task lists, strikethrough, links from bare URLs, and a filter for a few unsafe HTML tags.

Most modern tools follow CommonMark for the core. Many add GFM. Some add more on top, such as footnotes, math or diagrams. Those extras vary from tool to tool, so this guide leaves them out.

## Headings

Start a line with one to six `#` signs, then a space. One `#` is the top level. Six is the smallest.

```markdown
# Project plan
## Goals
### Open questions
```

The space after the `#` matters. `#Goals` with no space is plain text in CommonMark.

There is a second style for the top two levels: underline the text with `===` or `---`. You will see it in older files. The `#` style is easier to scan, so most people use it.

## Paragraphs and line breaks

A blank line starts a new paragraph. A single line break inside a paragraph does not show up. The renderer joins the lines with a space.

```markdown
This is one line.
This line joins the one above.

This is a new paragraph.
```

Result:

This is one line.
This line joins the one above.

This is a new paragraph.

To force a line break without a new paragraph, end the line with a backslash `\` or with two spaces. The backslash is easier to see, since trailing spaces are invisible.

## Emphasis: bold, italic and strikethrough

```markdown
*italic* or _italic_
**bold** or __bold__
~~struck through~~
```

Result:

*italic* or _italic_

**bold** or __bold__

~~struck through~~

Strikethrough is a GFM feature. In a tool without GFM, the tildes show as text.

## Lists

Start each item with `-`, `*` or `+` for a bullet list. Use a number and a period for a numbered list.

```markdown
- Read the plan
- Check the steps
  - Look at file paths
  - Look at commands

1. Open the file
2. Read the header
3. Read the steps
```

Result:

- Read the plan
- Check the steps
  - Look at file paths
  - Look at commands

1. Open the file
2. Read the header
3. Read the steps

A few rules save a lot of confusion:

- **Nesting.** Indent a child item so its marker lines up with the text of the parent. Under `- ` that is two spaces. Under `1. ` it is three.
- **Numbers.** The first number sets the start. The renderer counts up from there, so `1.` on every line still renders as 1, 2, 3.
- **Mixed markers.** Switching from `-` to `*` starts a new list. Pick one marker and keep it.
- **Blank lines.** Put a blank line before a list. A numbered list that starts at any number other than 1 cannot break into a paragraph, so without the blank line it stays part of the text above.

## Task lists

A task list is a list where items start with a box. `[ ]` is open. `[x]` is done.

```markdown
- [x] Write the plan
- [ ] Review the plan
- [ ] Run the tests
```

Result:

- [x] Write the plan
- [ ] Review the plan
- [ ] Run the tests

Task lists are a GFM feature. AI agents use them a lot in plans and to-do files. The rules, common mistakes and a way to count open items from the terminal are in [Markdown task lists explained](markdown-task-lists.md).

## Links

```markdown
[Example](https://www.example.com/)
[Plan notes](notes/plan.md "Optional title")
<https://www.example.com>
```

The first and last lines render like this:

[Example](https://www.example.com/)

<https://www.example.com>

The middle line becomes a link named "Plan notes" that opens `notes/plan.md`. The text in quotes shows as a tooltip.

The text goes in square brackets, the address in round brackets. Most viewers read a relative path such as `notes/plan.md` from the file's own folder. A leading `/` starts from a root, but whether that is the site or the disk depends on the viewer. Angle brackets turn a full web address, one that starts with a scheme such as `https://`, into a link in any CommonMark tool. GFM also links a bare `https://` or `www.` address with no brackets at all.

For long documents, reference links keep the text clean:

```markdown
See the [setup notes][setup].

[setup]: docs/setup.md
```

The definition can come before or after the link. Keep it outside code blocks, and put a blank line before it if it follows a paragraph. A valid definition does not show on the page.

## Images

An image is a link with a `!` in front. The text in square brackets is the alt text.

```markdown
![Diagram of the build steps](images/build.png)
```

Three things trip people up:

- **Relative paths.** Most viewers read them from the folder the Markdown file is in, so `images/build.png` is a folder named `images` next to the file. The Markdown spec leaves that to the viewer.
- **Alt text** is what a screen reader says and what shows if the image fails. Describe what the image shows.
- **Remote images** load from another server. Some viewers block them for privacy, since loading one sends a request to that server. If an image from a URL does not appear, that may be why.

## Code

Wrap a short piece of code in single backticks for inline code: `` `npm test` `` renders as `npm test`.

For a block, put three backticks on the line before and the line after. Add a language name after the opening backticks to get syntax highlighting in tools that support it.

````markdown
```bash
pnpm install
pnpm test
```
````

Result:

```bash
pnpm install
pnpm test
```

Three tildes `~~~` work the same way as three backticks. An older style indents every line by four spaces. It still works, but it cannot name a language.

## Block quotes

Start a line with `>`. Add a second `>` to nest.

```markdown
> The agent stopped here.
>
> > Waiting on Jane Doe for the API key.
```

Result:

> The agent stopped here.
>
> > Waiting on Jane Doe for the API key.

Agents often use quotes for notes, warnings and quoted output.

## Tables

```markdown
| Step | Owner    | Status |
|:-----|:--------:|-------:|
| Plan | Agent    | Done   |
| Review | Jane Doe | Open |
```

Result:

| Step | Owner    | Status |
|:-----|:--------:|-------:|
| Plan | Agent    | Done   |
| Review | Jane Doe | Open |

How it works:

- The first row is the header. The second row is dashes, one cell per column.
- A colon on the left of the dashes aligns left. Colons on both sides center. A colon on the right aligns right.
- The pipes do not need to line up. The table above renders the same either way.
- To put a pipe inside a cell, escape it as `\|`.

Limits worth knowing: a cell holds one line of text. GFM tables have no way to merge cells, and a cell holds only inline text, so a Markdown list cannot go inside one. For anything bigger, use a list or split the table.

Tables are a GFM feature. Without GFM, you see the pipes as text.

## Horizontal rules

Three or more dashes, asterisks or underscores on a line of their own draw a line across the page.

```markdown
Above the line.

---

Below the line.
```

Leave a blank line above `---`. Without it, dashes right under a line of plain text turn that text into a heading.

## Escaping special characters

Put a backslash in front of a symbol to show it as text instead of formatting.

```markdown
\*not italic\*
1\. not a list item
\# not a heading
```

Result:

\*not italic\*

1\. not a list item

\# not a heading

## Raw HTML

CommonMark lets you mix HTML tags into Markdown. GFM keeps that but filters a short list of risky tags, such as `<script>` and `<iframe>`.

In practice, support varies a lot. Some tools render the HTML. Some strip it. Some show it as plain text. If a file depends on HTML to look right, check it in the tool your readers use.

## Front matter

Many Markdown files start with a block of YAML between two `---` lines. This is front matter. It holds fields such as a title, a date or a status.

```markdown
---
status: in-progress
owner: Jane Doe
---
```

Front matter is not part of CommonMark or GFM. Tools that know about it hide it or show it as data. Tools that do not may show the first `---` as a line and the fields as a large heading, because the closing `---` underlines them. AI agents often put a front matter block at the top of [handoff files](what-is-an-agent-handoff-file.md).

## Quick reference

| You want | Type this |
|:---|:---|
| Heading | `## Heading` |
| Bold | `**bold**` |
| Italic | `*italic*` |
| Strikethrough (GFM) | `~~text~~` |
| Bullet list | `- item` |
| Numbered list | `1. item` |
| Task (GFM) | `- [ ] task` |
| Link | `[text](url)` |
| Image | `![alt](path.png)` |
| Inline code | `` `code` `` |
| Code block | three backticks before and after |
| Quote | `> text` |
| Table (GFM) | pipes and a dash row |
| Line | `---` with a blank line above |
| Literal symbol | `\*` |

## When it renders wrong

These three things cause many rendering problems:

1. **A missing blank line.** A blank line before any block is the safe habit. Without one, a numbered list that starts at 2 or higher, or an indented code block, joins the paragraph above.
2. **A missing space.** `#Heading` and `-item` stay plain text. So does a task box written `[]` with no space inside.
3. **A symbol read as formatting.** An asterisk, or an underscore at the edge of a word, can start italics. A pattern like `*.md` can trip this. Wrap paths and patterns in backticks or escape the symbol.

Look at the raw text when a page looks off. The cause is usually visible there in a few seconds.

## Where Skimmark fits

Skimmark is a Markdown reader and editor for people whose AI agents write Markdown. It is in development and has not been released. The app itself has no AI features.

Planned for v1: a live render of headings, lists, check-box lists, tables, code blocks, links, local images and block quotes. Remote images are not fetched, and raw HTML is shown inert. A Frontmatter Table shows the YAML header as key and value rows instead of raw text.

You can see what Skimmark is and follow along at [skimmark.com](https://www.skimmark.com/).
