Skip to content
Crixaa
← All posts

Why your PDF never quite matches your design

The Crixaa team3 min read

You lay out a document. The preview looks right. You generate the PDF, open it, and a heading has crept onto its own line, a paragraph you carefully sized now spills onto a second page, and the typeface is subtly not the one you picked.

This is so common that most people treat it as the cost of doing business with documents. It is not. It is a specific, fixable architectural problem.

Two engines, one guess

Almost every document tool has a browser-based editor and a server-side PDF generator. Those are two entirely different rendering engines. The browser lays out text using its own font stack and line-breaking rules. The PDF library does its own thing, with its own metrics.

Nobody wired them together. They just happen to be pointed at the same document, and any agreement between them is a coincidence — one that has to hold for every font, every size, every string your users pass in.

It usually holds for the example you tested with. It stops holding when a customer name is longer than the one you typed, or when the invoice has eleven line items instead of three.

Fonts are where it breaks first

The most common failure is the simplest. Your editor renders in a font the server does not have. The PDF library falls back to something else — often a metrically different face — and every line break in the document shifts.

You do not usually get an error. You get a document that is subtly wrong, and you find out when a customer tells you.

There are only two honest fixes:

  • Ship the same fonts to both sides, or
  • Refuse to offer fonts you cannot render.

We do both. Three families — Inter, Source Serif 4 and JetBrains Mono — are embedded in the browser and in the PDF renderer. Pick something outside that set and it is mapped to a supported family deliberately, in the editor, where you can see it happen. What you cannot do is quietly get a substitution at render time.

Measuring in two places is the same bug

Fonts are the visible half. The subtler half is layout measurement.

If your editor decides a paragraph is 84 points tall and the PDF engine decides it is 91, everything below it moves. Neither number is wrong — they are answers from two different systems to a question that was asked twice.

So we stopped asking twice. The canvas asks the PDF engine what it would compute, and uses that answer. There is one measurement authority, and both sides defer to it.

That has a pleasant side effect: because the editor knows the real rendered height of every element, it can tell you when text is about to overflow its box. You find out while you are designing, not after you have sent a thousand documents.

What this costs

Honesty requires the trade-off. Sharing a rendering contract means the editor cannot offer things the PDF engine cannot do. There is no arbitrary web font picker. There are no CSS effects that quietly degrade on export.

We think that is the right trade. A document tool that offers a control and then ignores it is not more powerful — it is just less truthful. The rule we hold ourselves to is that the editor should never show a control the renderer would silently drop.

The test that matters

If you are evaluating any document tool, including this one, the useful test is not the demo template. It is this:

  1. Rebuild a document you actually send.
  2. Generate it with your longest real customer name, not Acme Corp.
  3. Generate it again with three times as many line items as usual.

If it survives all three, the tool is doing something real about this problem. If it does not, you now know exactly which part to ask about.

Try it on your own document

Design a template in the browser and generate a real PDF — free, no card.