A web page scrolls forever. A PDF has pages. Everything that goes wrong in this conversion happens where the converter decides to cut.
Why the layout breaks
The converter loads your page in a real browser engine, applies your CSS, then slices the rendered result into paper-sized pieces. It is the same machinery as Print to PDF, which is why the two produce nearly identical output.
The trouble is that your CSS was written for a viewport that scrolls. Several things behave differently once there are pages:
position: fixedpins to the page, so a sticky header repeats on every single page.- Viewport units resolve against the paper, so
100vhbecomes a full sheet rather than a screen. - Backgrounds are dropped by default. Browsers omit background colours and images when printing unless told otherwise.
- Anything can break mid-element — a table row split across two pages, a heading orphaned at the foot of one.
- Lazy-loaded images may never load, because nothing scrolls to trigger them.
None of these are converter bugs. They are the correct rendering of CSS that assumed a screen.
The print stylesheet does most of the work
A short @media print block fixes the majority of layout problems, and takes minutes to write.
| Rule | Fixes |
|---|---|
position: static on fixed elements | Headers repeating on every page |
break-inside: avoid on cards and rows | Elements split across a break |
break-after: avoid on headings | A heading stranded at the page foot |
print-color-adjust: exact | Missing background colours |
display: none on nav and footers | Site furniture in a document |
@page { margin: 20mm } | Content in the unprintable margin |
| Absolute units for type | Unpredictable sizing from rem or vw |
The unprintable-margin one matters more than it looks: no consumer printer reaches the edge of the sheet, so content within about 5mm of it is lost. The detail is in why your PDF will not print properly.
Images and fonts
Two things go missing for the same underlying reason: the converter fetches resources, and anything it cannot fetch in time is simply absent.
Images. Lazy loading is the usual culprit — nothing scrolls, so nothing triggers. Relative paths break if the converter renders from a string rather than a URL. Set loading="eager" for print, or inline critical images as data URIs.
Fonts. A webfont that has not finished loading when the render fires gets substituted, which changes every metric on the page. Some converters wait for document.fonts.ready and some do not.
If a converted document has the right text in the wrong font with reflowed lines, that is a font timing problem, not a CSS one. Embedding the font or allowing a longer render delay fixes it.
Interactive elements do not survive
A checkbox in HTML is an input element. A checkbox in a PDF is an AcroForm field. They are unrelated objects, and no HTML-to-PDF converter creates the second from the first.
What you get is a picture of a checkbox in whatever state it was rendered in. The same applies to select menus, radio buttons, text inputs and anything driven by JavaScript.
If the output needs to be fillable, the HTML route cannot produce it. Generate a flat PDF and add form fields with a PDF tool afterwards, or build the form in a PDF editor from the start. Converting an HTML form and expecting a working PDF form is the single most common wasted afternoon in this subject.
Newsletters and email HTML
Email HTML is a special case and converts worse than ordinary web pages, for a reason that is nobody's fault.
Email clients only support a narrow, dated subset of CSS, so newsletters are built with nested tables, inline styles and spacer images. That renders acceptably in an email client and often poorly in a browser engine, which applies modern layout rules to markup written to avoid them.
The practical route for a newsletter is to open the hosted web version — most senders provide a "view in browser" link — and convert that instead. It is normal HTML, written for a browser, and converts like one.
Frequently asked questions
Why does my header repeat on every page of the PDF?
Because it uses position: fixed, which pins to the page rather than the document once there are pages. Set it to position: static inside an @media print block and it appears once, in the flow.
Why are the background colours missing?
Browsers omit background colours and images when printing by default, to save ink. Add print-color-adjust: exact (with the -webkit- prefix for older engines) to the elements that need them.
Why did my images not appear?
Usually lazy loading — nothing scrolls during conversion, so the images are never triggered. Set loading="eager" for print, or inline critical images as data URIs. Relative paths also break if the converter renders from a string rather than a URL.
Can I convert an HTML form into a fillable PDF?
No. An HTML input and a PDF AcroForm field are unrelated objects, and no converter creates the second from the first — you get a picture of a checkbox in whatever state it rendered. Add the form fields with a PDF tool afterwards.
How do I stop tables splitting across pages?
break-inside: avoid on the rows or on the table, inside an @media print block. Pair it with break-after: avoid on headings so a heading is not stranded alone at the foot of a page.
Why does my email newsletter convert badly?
Because email HTML is built with nested tables and inline styles to survive email clients, and a browser engine applies modern layout rules to markup written to avoid them. Convert the hosted "view in browser" version instead — that is ordinary HTML.