Public API is now available! Convert Markdown to images programmatically with 50 free requests/month.
Back to Blog
Thursday, January 1, 1970

Markdown to PDF with Code Highlighting: How to Preserve Syntax Colors

Markdown to PDF with Code Highlighting: How to Preserve Syntax Colors

The short answer

If you want a Markdown → PDF that keeps code highlighting (colors, font, line numbers), use a headless-Chromium based tool. Our /markdown-to-pdf does this out of the box — fenced code blocks render with full Prism / highlight.js color, monospace font, and proper line-wrapping, and the PDF is exactly what the preview shows.

The rest of this guide explains why most Markdown → PDF tools strip or distort code colors, the three things that have to line up to keep them, and how each common tool stacks up.

Why Markdown PDFs often lose code highlighting

Three separate failure modes show up in the wild:

  1. The renderer never highlighted in the first place. Plain pandoc input.md -o output.pdf ships highlighting via Listings/Skylighting, which produces dated, low-contrast PDF colors that look nothing like a web syntax theme. Without --highlight-style, you might get monochrome.
  2. The highlighter ran, but print CSS killed it. When you ⌘+P from a browser, many sites have a print stylesheet that resets color: black !important. Code blocks come out as pure black on white — readable but unhelpful for scanning structure.
  3. The PDF engine stripped colors during conversion. Some older PDF libraries flatten everything to grayscale on certain printer profiles. A common giveaway is that links keep their blue but code blocks don't keep their green/orange.

If you've ever exported a Markdown doc and seen monochrome code where you expected a syntax theme, it was almost always one of those three.

Three things that must line up

Keeping code highlighting in a PDF is a chain. If any link breaks, the colors don't survive:

  1. A real syntax highlighter renders the source. Prism, highlight.js, Shiki, or Pandoc's Skylighting. Without one, code is just monospace text.
  2. The theme survives the print path. Either the tool exports the screen rendering directly (headless Chromium) or it has an explicit print stylesheet that doesn't reset colors.
  3. The fonts and colors match the theme's intent. Dark themes (Dracula, One Dark) on white paper backgrounds look terrible when printed; light themes (GitHub Light, Solarized Light) print well.

The browser-based path keeps all three by default — the screen render and the PDF render are the same Chromium snapshot.

Method-by-method comparison

/markdown-to-pdf (web tool)

Uses headless Chromium to capture exactly the preview as PDF. Fenced code blocks use Prism by default with a built-in light theme tuned for printing. Long lines wrap with a soft indent rather than overflowing the page. Inline code keeps its background and monospace font.

Verdict: works out of the box. No config needed.

md-to-pdf (npm CLI)

Also headless Chromium under the hood, but you control the highlight.js theme via YAML front-matter:

---
stylesheet:
  - https://cdn.jsdelivr.net/npm/highlight.js/styles/github.css
---

Verdict: full color, but you bring the theme. Try github.css for light printing, atom-one-dark.css if you genuinely want a dark PDF.

VSCode "Markdown PDF" plugin

Uses Chromium too, but the default highlight theme is the editor's current theme. If you're on a dark theme in VSCode, your PDF gets a dark background — fine for screen, expensive in toner if printed. Override in user settings:

"markdown-pdf.highlightStyle": "github.css"

Verdict: works, but check the theme before printing.

Pandoc

Pandoc's default code rendering uses Skylighting, which is a custom highlighter different from highlight.js / Prism. The colors look dated by web standards. Pass --highlight-style=tango (or pygments, kate, monochrome) for a different palette. None of them match a modern web theme exactly.

If you want a web-style theme through Pandoc, the trick is to convert via HTML first:

pandoc input.md -o output.html --highlight-style=pygments --self-contained
# then print the HTML to PDF in a browser

Verdict: works, but indirect. Most users picking Pandoc don't pick it for web aesthetic.

Browser print (Save as PDF)

Depends entirely on the print stylesheet. Github.com's print CSS preserves colors decently. Some doc sites strip them aggressively. Test before relying on it for an important deliverable.

Verdict: hit-or-miss.

Picking a theme that prints well

A few practical notes:

  • Light themes print better. Dark backgrounds are murder on toner and on contrast in B&W printers. Use GitHub Light, Solarized Light, or Atom One Light.
  • Avoid extremely saturated colors. Pure red and pure green look harsh on paper. Themes with desaturated palettes (Solarized Light, Tomorrow) read better in print.
  • Test with line numbers off first. Line numbers on long code blocks shift the right edge and can collide with page margins.
  • Watch your monospace font. If the theme requires a font you don't have, you fall back to Courier, which looks dated. Inter, JetBrains Mono, or Fira Code are safe defaults if available.

Common pitfalls

  • Long lines overflow. Wrap soft-wrap with pre { white-space: pre-wrap; } if you control the CSS, or break the lines manually before exporting.
  • Tabs vs spaces. PDFs render tabs at whatever the renderer thinks; if your code uses tabs and the alignment matters, normalize to spaces first.
  • Curly quotes. Some Markdown processors smart-quote code inside backticks, breaking syntax. Disable smart-quotes for code (Pandoc: --from=markdown-smart).
  • Emoji in comments. Many PDF fonts don't include color emoji. They render as black-and-white outlines or ? boxes. Strip emoji from code comments if you need print-perfect output.

FAQ

Does /markdown-to-pdf support Prism / highlight.js themes?

It uses Prism with a built-in print-tuned theme. If you need a specific theme, the CLI route is more flexible. See our 5-method comparison.

Why does my code look colorless in the PDF but colored in the preview?

The most likely cause is a print stylesheet on the source page. Browser print honors @media print rules, which often reset colors. The web-based /markdown-to-pdf doesn't have this issue because it captures the screen rendering directly.

How do I keep line numbers in the PDF?

The web tool doesn't show line numbers by default — they're more useful for debugging than for sharing. If you absolutely need them, the md-to-pdf CLI plus a highlight.js theme that includes .hljs-ln-numbers will preserve them.

What's the best theme for a printed PDF?

GitHub Light. It's the most familiar to readers (looks like the README on GitHub.com), prints well in both color and B&W, and the contrast is good without being garish.

Can I batch-convert dozens of files and keep highlighting?

Yes — see Batch convert Markdown to PDF. The CLI methods are best for batch.

Wrapping up

Keeping code highlighting in a Markdown → PDF is straightforward if you use a tool that renders through real Chromium. /markdown-to-pdf handles it without configuration; the npm CLI gives you per-document theme control; everything else is a tradeoff between convenience and color fidelity.

Markdown to PDF with Code Highlighting (Preserve Syntax Colors) | MarkdownToImage