Fenced Code Blocks and Syntax Highlighting in Markdown, Explained
A fenced code block is the cleanest way to drop code into a Markdown document. You wrap the code in a line of three backticks above and below, and everything in between is preserved exactly as you typed it. Add a language name right after the opening fence and most renderers will color the code so it reads more easily. That is the whole feature. The details are where people trip.
Quick answer (one-paragraph TL;DR)
A fenced code block opens with at least three backticks ( ` ) or three tildes (~~~) on their own line, and closes with a matching fence. The text inside is literal: Markdown won't touch the asterisks, underscores, or angle brackets in your code. Put a language identifier immediately after the opening fence — js, python, swift — and the renderer switches on syntax highlighting by tagging the block with that language. No identifier, no colors, but the code still renders in plain monospace. Here is a real one:
def greet(name):
return "Hello, " + nameFor the rest of the syntax around it, our Markdown syntax cheat sheet covers headings, lists, and links.
How it actually works
A code fence is a sequence of at least three backticks or three tildes, indented no more than three spaces. You can't mix the two characters in one fence, and the closing fence has to use the same character as the opener and be at least as long. That's straight from the CommonMark spec, which defines the behavior every modern renderer follows.
The line that opens the fence can carry an info string — the text after the backticks. Renderers read the first word of that info string as the language and write it into the class attribute of the generated code element, usually as something like language-python. A highlighter then maps that class to a grammar and colors the tokens. GitHub does this with Linguist, the same library it uses to detect file languages across a repository.
It helps to know that fences are a later addition. The original Markdown by John Gruber, released in 2004, had no fences at all — you marked code by indenting every line four spaces. Fenced blocks came from dialects like PHP Markdown Extra and were later standardized by CommonMark and adopted by GitHub Flavored Markdown, which is now a strict superset of CommonMark. If you want the full rundown of those dialects, see our breakdown of CommonMark vs GitHub Flavored Markdown.
To choose a language, the identifier sits on the opening line:
let greeting = "Hello, world" print(greeting)
A few rules save you grief. The info string can't contain backticks. If your code itself includes a run of three backticks, open the outer block with four backticks so the inner ones render as text — a trick GitHub's own guide recommends. And a blank line before and after the block keeps the raw file readable.
When to use it (and when to skip it)
Reach for a fenced block whenever the code is more than a fragment: a function, a config file, a shell session, a JSON payload. Fences preserve indentation and special characters, which is exactly what code needs. For a single variable name or a one-word command inside a sentence, use inline code — a single backtick on each side — instead.
Now the honest part. Syntax highlighting is cosmetic. It does not check your code, and the language label is a hint rather than a guarantee: a misspelled identifier like pyton simply falls back to no colors. Highlighting also shifts from one renderer to the next. The same block can look different on GitHub, in a static-site generator, and in your editor, because each one picks its own grammar and theme.
Markdown's code support is deliberately spare. There are no line numbers, no diff coloring, and no semantic understanding baked into the format itself — those belong to whatever tool renders or edits the file. That keeps the format portable, but it means your editor is doing the heavy lifting. For laying out tabular data alongside your snippets, our guide on how to write Markdown tables picks up where code blocks leave off.
How Carets fits in
This is where the editor earns its place. Carets is a fast, native notes and code editor for iPhone, iPad, and Mac that treats Markdown, plain text, and code as equals. A fenced block tagged swift or python gets syntax highlighting as you type, not only after you publish it somewhere. Because your notes stay plain text, the file you edit on a Mac opens unchanged on an iPhone, and the fences travel with it to GitHub, a static site, or any other Markdown renderer.
Two things make it fit this topic in particular: syntax highlighting for code and config files is built in, and it is native rather than a web wrapper, so editing a long snippet on a phone stays responsive. You keep snippets, README drafts, and scratch files organized into files, projects, and tags instead of scattered across apps — which is the whole appeal of plain text for writers and developers alike. Carets is available on the App Store for iPhone, iPad, and Mac.
Frequently Asked Questions
What's the difference between fenced and indented code blocks?
Indented code blocks — the original Markdown style — mark code by indenting every line four spaces. Fenced blocks wrap the code in triple backticks or tildes instead. Fences are easier to read and edit, and they're the style that supports a language identifier for syntax highlighting.
Do I have to specify a language?
No. The language identifier is optional. Without it, the block still renders as preformatted monospace text; you just don't get colored tokens. Add one — like bash or json — when you want highlighting.
Why isn't my syntax highlighting showing up?
Three usual suspects: a misspelled language identifier, a renderer that doesn't support highlighting, or a fence that was never closed. Confirm that the opening and closing fences use the same character and that the language name is one the renderer recognizes.
Can I show literal backticks inside a code block?
Yes. Wrap the block in one more backtick than it contains. If your code has a triple-backtick run, open and close the outer block with four backticks so the inner three render as plain text.