How to write a code block in markdown

Updated

To write a code block in markdown, put the code between two lines of three backticks (a fence) and name the language after the opening fence to get syntax highlighting:

```python
def greet(name):
    return f"Hello, {name}"
```
def greet(name):
    return f"Hello, {name}"

Inside the fence nothing is interpreted: no bold, no links, no HTML, and whitespace is preserved exactly. The language tag is optional and the fence works without it. Everything else on this page is about the edges: inline code in a sentence, backticks inside code, fences inside lists, the special fences GitHub and GitLab turn into diagrams, and the apps that render fences without highlighting or not at all.

How do you write inline code?

For a snippet inside a sentence, wrap it in single backticks: `npm install` renders as npm install. Inline code is for identifiers, commands, file names, keys and values in prose; it gets a monospace font and a light background but no syntax highlighting. A backtick inside inline code needs a double-backtick wrapper with a space inside: `` a `tick` inside `` renders as a `tick` inside. The escaping guide covers the other characters that need help in prose.

Which language tags can you use?

Whatever the renderer's highlighter recognises. GitHub uses the Linguist language list and documents it in creating and highlighting code blocks; GitLab uses Rouge; most web renderers use highlight.js or Prism. The common tags are safe in all of them:

TagAlso acceptedNotes
jsjavascript, jsx, ts, typescript, tsx
pythonpy
bashsh, shell, zsh, consoleconsole highlights the $ prompt in some highlighters
json, yaml, toml, xml, html, cssyml
sql, go, rust, c, cpp, java, csharp, ruby, php, swift, kotlinrs, cs, rb
markdownmdUse it for markdown examples, as on this page
textplaintext, txt, nothingExplicitly no highlighting
diffLines starting with + and - are coloured green and red

The diff tag is the most useful one people do not know about:

- const port = 3000;
+ const port = process.env.PORT ?? 3000;

Tags are case-insensitive on GitHub, but GitHub Pages (Jekyll) wants them lower case. An unknown tag never breaks the block; it just renders without colour.

How do you show backticks inside a code block?

Use a longer fence than anything inside. A block that contains a three-backtick fence needs a four-backtick fence around it, which is how the first example on this page is written, and GitHub's docs give the same advice. Tildes work as fences too (~~~), so a tilde fence can wrap a backtick fence and vice versa:

````markdown
```js
console.log("nested")
```
````

The opening and closing fences must match in character and the closing fence must be at least as long as the opening one. A closing fence indented by up to three spaces still closes the block, which matters when a fence sits inside a list.

Should you use fenced or indented code blocks?

Fenced. Indenting a block by four spaces also makes a code block (the original markdown form), but fences take a language tag, need no re-indentation when you paste, cannot be created by accident, and work inside lists without the double-indent dance. Indented blocks are the cause of the most common markdown bug, prose that turns into a code box because it was pasted with leading spaces, and MDX does not support them at all. The one place the indented form is still useful is a renderer that has no fences, which today is old Reddit.

How do you put a code block inside a list item?

Indent the fence and the code to the list item's content column (2 spaces under - , 3 under 1. ), with a blank line before the fence:

1. Install the dependencies:

   ```bash
   npm install
   ```

2. Start the server.

The code keeps its own indentation relative to the fence. If the fence sits at column 0 the list ends, and the next number restarts at 1. GitHub's docs note that a non-fenced block inside a list needs eight spaces of indentation, which is one more reason to fence. The nested list guide covers the column rules for everything else that lives inside a list item.

Where do code blocks render?

AppFencesHighlightingIndented blocksInline codeSource
GitHubYes; also ~~~Yes, LinguistYesYesGitHub code blocks
GitLabYes; also ~~~Yes, RougeYesYesGitLab code spans and blocks
ObsidianYes; also ~~~YesYesYesObsidian syntax
Notion/code block (or Cmd/Ctrl+Option/Shift+8) with a language picker; pasted fences convert on .md importYesNoYesNotion shortcuts
DiscordYes, with a language tagYes, for common languagesNoYesDiscord Markdown Text 101
SlackYes; no language tagNoNoYesSlack formatting
RedditNew Reddit markdown mode and rich editorNoYes (old Reddit needs this)YesReddit markdown sheet
Jira CloudTyping ``` converts to a code block; {code:java} in legacy wiki markupYesNoYesJira shortcuts
MDXYesVia the site's plugin (Prism, Shiki)NoYesMDX docs
PandocYes, plus attributes like {.python .numberLines}In HTML, LaTeX and docx outputYesYesPandoc fenced code

A code block is the usual fallback for a table in Slack and Discord, where tables do not render but monospace columns line up. The Slack and Discord sheets cover each app's remaining syntax.

Which special fences do GitHub and GitLab render?

Some language tags turn the block into something other than code:

TagGitHubGitLabWhat it renders
mermaidYesYesFlowcharts, sequence diagrams, Gantt charts from text
mathYesYesLaTeX math, see the math guide
geojson, topojsonYesNoAn interactive map
stlYesNoA 3D model viewer (ASCII STL)
plantumlNoYes (with a PlantUML server configured)UML diagrams
suggestionIn PR review commentsIn MR commentsA one-click applicable code change

Everywhere else these are plain code blocks with an unknown language, which is harmless: the text shows, uncoloured.

Can you add line numbers, a title or highlighted lines?

Not in GFM. GitHub and GitLab show no line numbers in rendered markdown and have no title syntax; the file name goes in the sentence before the block or in a comment on the first line of the code. Docs generators add their own extensions, all of which print literally on GitHub:

ToolLine numbersTitleHighlight lines
DocusaurusshowLineNumbers after the tagtitle="file.js"{2,4-6} after the tag, or // highlight-next-line
MkDocs Materiallinenums="1"title="file.js"hl_lines="2 3"
Pandoc{.python .numberLines startFrom="10"}NoNo
Hugo{linenos=true}No{hl_lines=[2,3]}

If a README will also be built by one of these tools, keep the GitHub form in the README and the extended form in the docs source.

Why is my code block not highlighting or not closing?

  1. Unsupported or misspelled tag. javascrip or c# (use csharp) gives no colour; the block still renders.
  2. Text after the language. Most renderers want only the tag on the opening fence line; js (example) disables highlighting on some.
  3. Unclosed fence. Everything to the end of the document becomes code. Count your fences; the closing one must be as long as the opening one.
  4. Fence inside a list at the wrong column. It either ended the list or became part of the previous paragraph. Indent it to the item's content column.
  5. The app has no highlighting. Slack renders the block but ignores the tag; Reddit likewise.
  6. Backticks that are not backticks. Text pasted from a word processor often has curly quotes or acute accents (´) in place of `.

Run the file through the markdown viewer to see the fence structure as GitHub parses it, or the markdown formatter, which normalises fence lengths. For the rest of the syntax see the markdown cheat sheet.

Keep going