Markdown is a forgiving language. PDFs are not. Eight bugs turn a clean .md file into a broken PDF — diagnosed, with the quick fix and the structural fix for each.
TL;DR — the eight bugs
Almost every markdown to PDF formatting issuetraces back to one of three structural causes: the converter uses a Chromium print engine that wasn’t built for typography, the rendering passes happen in the wrong order, or the source content was authored for the screen and the PDF inherited the screen’s assumptions. The fixes fall into the same three buckets.
- Tables overflow or break across pages.
- Code blocks lose syntax highlighting.
- Page breaks land mid-image or mid-heading.
- Footnotes disappear or merge.
- Custom fonts don’t embed.
- Math (KaTeX/LaTeX) doesn’t render.
- Images pixelate at print resolution.
- Table-of-contents page numbers are wrong.
Each gets a quick fix you can apply today and a structural fix that prevents the bug from recurring. The structural fix is almost always the same recommendation: use a converter built for designed output (mdclaudy, Pandoc with Eisvogel, Typst) rather than a tool that wraps browser print.
The eight bugs at a glance
| Symptom | Root cause | Quick fix | Structural fix |
|---|---|---|---|
| Tables overflow or break across pages | Wider than the page; no column scaling; CSS page-break-inside ignored | Rotate to landscape or shrink the font for tables | Use a template that sizes tables to column and repeats headers |
| Code blocks lose syntax highlighting | Highlighter ran in the editor but the export pipeline strips classes | Pre-render with highlight.js or Prism before export | Use a converter that highlights server-side (Pandoc + listings, mdclaudy) |
| Page breaks land mid-image or mid-heading | Browser print uses CSS heuristics; no widow/orphan control | Add a hard page break before the affected element | Use a Typst or LaTeX engine with real widow/orphan control |
| Footnotes disappear or merge | Most Chromium converters don't implement footnote pagination | Convert footnotes to endnotes manually | Use Pandoc or a template with footnote-aware pagination |
| Custom fonts don't embed | Font referenced by name but not subsetted into the PDF | Convert text to outlines (loses copy-paste) | Use a converter that subsets fonts on export (mdclaudy does) |
| Math (KaTeX/LaTeX) renders as raw $...$ | No math rendering pass between markdown and HTML | Convert math to images in Notion or Obsidian first | Use Pandoc --mathjax or a tool with first-class KaTeX |
| Images pixelate at print resolution | Source image is screen-resolution (72-96 dpi); PDF needs 300 | Resize the source up before embedding | Embed SVG where possible; raster at 2x source for 150dpi |
| Table of contents page numbers are wrong | TOC generated before final pagination; no second pass | Manually update TOC after export | Use a tool that does a two-pass render (Pandoc, mdclaudy) |
1. Tables overflow or break across pages
The single most reported bug in any markdown-to-PDF pipeline. You write a tidy GFM table; the PDF shows a table that runs off the right edge of the page or splits across pages with no header repeat.
Why it happens
Three reasons usually compound. The table is wider than the page in characters. The CSS doesn’t scale columns to fit. And the Chromium printer ignores page-break-inside: avoidfor large blocks — there’s nowhere else to put a 40-row table.
How to fix it
- Quick: rotate the page to landscape with a per-page CSS rule, or drop the font size for the table.
- Better: add
<style>table { width: 100%; table-layout: fixed; word-break: break-word; }</style>to your CSS so columns share the available width. - Structural: use Pandoc with the
longtableLaTeX package (Eisvogel includes it), or mdclaudy’s templates, which size tables to column and repeat the header on every page. For the markdown-side of tables, see the guide at markdown tables.
2. Code blocks lose syntax highlighting
You wrote ```python, the editor showed colored tokens, the PDF shows monochrome text. The highlight worked in the editor; it didn’t survive the export.
Why it happens
Most editors apply highlighting via a client-side library (highlight.js, Prism, Shiki) at render time. The export pipeline either strips the resulting <span class="hljs-keyword"> tags or hits the print job before highlighting completes.
How to fix it
- Pandoc: add
--highlight-style=pygments(or one of the built-in styles liketango,kate,monochrome). With Eisvogel, also pass--listingsfor proper code formatting. - md-to-pdf: configure the markdown-it highlight callback in the config file to call
highlight.jsin Node before render. - VS Code Markdown PDF:the extension reads VS Code’s color theme — it works if your theme is light, breaks on dark themes. Switch to a light theme before export.
- mdclaudy: highlighting is server-side by default, themed to match the template. No configuration.
3. Page breaks land mid-image or mid-heading
A heading sits alone at the bottom of page 4. An image splits halfway across the page boundary. A paragraph ends one orphaned line on the next page. The PDF reads as broken because the breaks don’t respect the structure of the document.
Why it happens
The Chromium print engine implements only a subset of the CSS Paged Media spec. Widow/orphan control is partial; break-after and break-before are honored unevenly; page-break-inside: avoid fails on tall elements. LaTeX and Typst engines do this correctly because they were built to.
How to fix it
- Force a break: insert
<div style="page-break-before: always" />in markdown before a heading that should start on a new page. In Pandoc, the equivalent is\newpage. - Keep elements together: wrap an image and its caption in a
<div style="page-break-inside: avoid">— works in most Chromium converters. - Structural:use Pandoc with Eisvogel (handles widows/orphans via LaTeX), or mdclaudy’s designed templates, which set
widows/orphansto 3 by default.
4. Footnotes disappear or merge
You wrote [^1] in markdown. In the PDF, the footnote markers are gone, or all the footnotes are crammed at the end as endnotes, or every footnote on a page renders as 1.
Why it happens
Footnote pagination is one of the harder problems in document rendering. Most Chromium converters skip it — there’s no native CSS for footnote-at-bottom-of-page. Pandoc does it correctly via LaTeX. mdclaudy’s designed templates implement it explicitly.
How to fix it
- If you’re on Pandoc: make sure the reader is
markdownorgfm+footnotes, notmarkdown_strict. Eisvogel handles the rest. - If you’re on a Chromium pipeline: accept that footnotes will render as endnotes at the document end, or rewrite inline.
- If you’re on mdclaudy:footnotes render at the bottom of the page they’re cited on, with proper numbering carry-over between pages.
5. Custom fonts don’t embed
You set font-family: "Charter" in your CSS. The recipient opens the PDF and sees Times New Roman. Or worse — Arial.
Why it happens
A PDF must embed the font for the recipient to see it, not just reference it by name. Browser print embeds whatever font is loaded in the print job, but only as a subset of the glyphs used — and only if the converter passes the font through to the PDF. Some Chromium-based tools strip embedded fonts at export to keep PDFs small.
How to fix it
- Use a font loaded by URL, not by name: in CSS, use
@font-facewith a local file or a URL. Browser print handles this better than name-only references. - Pandoc with XeLaTeX:
pandoc input.md --pdf-engine=xelatex --variable mainfont="Charter" -o out.pdfembeds the font properly. - mdclaudy: the templates ship with embedded fonts; the export subsets them into the PDF automatically.
6. Math (KaTeX/LaTeX) doesn’t render
You wrote $\frac{a}{b}$. The PDF shows $\frac{a}{b}$. The math didn’t render at all, or it rendered in the editor but not in the export.
Why it happens
KaTeX is a JavaScript library — it transforms LaTeX-style math into HTML at render time, in the browser. The Chromium printer captures whatever is in the DOM at print time, so if the print fires before the KaTeX pass completes, you get raw markdown.
How to fix it
- Pandoc:
pandoc input.md --mathjax -o out.pdfor--katexto render math properly to MathML / images. - md-to-pdf: add a
markdown-it-katexplugin via the config file; the rendering happens in Node before the print job fires. - mdclaudy: KaTeX renders server-side as part of the export pass — you get the same math in the PDF that you see in the editor.
7. Images pixelate at print resolution
The image looks crisp in the editor. In the PDF, especially when printed, it looks blurry.
Why it happens
Screen images are 72 to 96 dpi. Print is 300 dpi. When a 600px-wide screenshot is embedded at 6 inches wide in the PDF, it’s effectively 100 dpi — fine on screen, blurry when printed.
How to fix it
- Export source images at 2x or 3xthe size they’ll appear at. macOS “take a screenshot” at 2x retina works; on Linux/Windows use a screenshot tool that captures at scale.
- Use SVG where possible — diagrams, charts, icons, logos. SVG is vector; it stays crisp at any size.
- mdclaudywarns at export when an image’s effective dpi is below 150 — it’s the cheapest QA check we could ship.
8. Table of contents page numbers are wrong
Your TOC says “Chapter 3 — page 12”. Chapter 3 is on page 17. The page numbers are off by a few, or wildly off.
Why it happens
Generating an accurate TOC needs the document’s final pagination, which depends on the TOC itself — a chicken-and-egg problem. The fix is a two-pass render: lay out without a TOC, measure page numbers, lay out again with the real TOC. Most one-pass Chromium converters skip this.
How to fix it
- Pandoc: two-pass is the default with
--toc --pdf-engine=xelatex. - md-to-pdf: generate the TOC manually, then export.
- mdclaudy: two-pass renders ship in Phase 1 — TOC page numbers match the document.
Most markdown-to-PDF bugs aren’t bugs in the markdown. They are bugs in the renderer pretending to be a typographer.
The structural fix, in one sentence
Use a tool that was built for designed output, not a tool that wraps browser print. Pandoc + Eisvogel and Typst-based tools fix most of the bugs above by virtue of their engines. mdclaudy fixes them by virtue of its templates. If your tool ends in “PDF” and starts with “print to”, you will keep fighting Chromium.
Adjacent reading
- Markdown to PDF: the complete guide — the eight methods compared.
- Notion PDF export looks bad — the 60-second fix — Notion-specific causes and the markdown bridge fix.
- Free markdown to PDF, no watermark — when free converters add the worst formatting issue of all.
- Markdown table syntax and tools — the source-side of table problems.
- Best markdown editors of 2026 — the editor side of the pipeline.
Frequently asked questions
The honest final word
You can spend a week tuning CSS to coax a browser-print pipeline into producing a presentable PDF. Or you can use a tool whose entire job is the PDF and ship the same afternoon. Both are valid choices. The first one teaches you a lot. The second one ships the document.
If the document is the point — and it usually is — let the tool do the typography. Try mdclaudy at /tools/markdown-to-pdf, or sign up at /sign-up for the library and the full template set.