Text and fonts
Custom fonts fall back to a default in the PDF
The document renders in Times or a generic sans-serif instead of your brand typeface. Spacing and line breaks differ from the browser preview, because the fallback font has different metrics.
What is actually happening
The font file was not fetched. A @font-face rule pointing at a relative path, a font hosted behind your application's authentication, or a font loaded by a script that ran after the snapshot all produce this. There is no error: an unavailable font falls back silently, which is the whole design of the font stack.
Confirming it is this and not something that looks like it
Set the font-family to something absurd that definitely does not exist. If the output looks identical to what you have now, the real font was never loading either.
The fix
Serve the font from an absolute public URL, or embed it as a data URI in the @font-face rule. Embedding is the reliable option and adds roughly the size of the font file to each request, which for a subset weight is tens of kilobytes rather than hundreds.
/* Absolute, public, and with the format so the engine does not guess. */
@font-face {
font-family: "Brand Sans";
src: url("https://assets.example.com/fonts/brand-sans-400.woff2") format("woff2");
font-weight: 400;
font-style: normal;
/* block, not swap: a document should wait for the right font rather than
paginate with the wrong metrics and never reflow. */
font-display: block;
}
.document {
font-family: "Brand Sans", Arial, sans-serif;
}If that was not it
These produce the same symptom often enough to be worth ruling out before assuming the fix above did not work.
- font-display: swap, which paginates with the fallback metrics if the font is slow
- Only one weight loaded while the CSS asks for 600, producing a synthesised bold with wrong widths
- A font host that blocks requests without a browser Referer
- Variable fonts declared without a font-weight range, so no weight matches
Frequently asked
Does this happen with every rendering engine?
The behaviour behind it is not specific to one tool. The font file was not fetched. Anything rendering HTML to a paged medium has to make the same decision, so the fix travels with you if you change how the render happens.
Will this show up as an error in my logs?
No, and that is what makes it expensive. A document that renders wrong is still a successful render as far as every log line is concerned. It is found by someone opening the file, which is usually the customer.
Related failures
Problems people arrive at from the same starting point, or mistake for this one.
Emoji do not render in the PDF
Emoji need a dedicated font, and colour emoji need one in a colour font format.
Text in the PDF cannot be selected or searched
The text is not text.
Line breaks in the PDF differ from the browser preview
The font is not the same.
Chinese, Japanese or Korean characters show as boxes
The font in use has no glyphs for those characters, and no font on the render machine does either.
Arabic or Hebrew text renders backwards or disconnected
Two separate problems.
CSS for paged documents, and what actually works
Which parts of the paged media specification a browser-based render implements.
Everything that goes wrong, by category
The full list, grouped by where in the pipeline it breaks.
Paste your markup and see the rendered document, without signing up.