← All guides

Fix: CSS styles lost when converting HTML to PDF

If your HTML looks right in the browser but the PDF comes out unstyled, missing colors, wrong fonts, broken layout, the cause is almost always one of a handful of predictable things, and the biggest by far is external resources not loading: many converters cannot fetch stylesheets, fonts, or images referenced by URL, so anything not embedded directly in the HTML is dropped. The other frequent culprits are missing @media print handling, background colors stripped by the browser's print mode, and viewport-relative units (vw/vh) that collapse on a fixed page. The reliable fix is to inline your CSS and fonts into the HTML rather than linking them, plus set explicit print styles. PDFMoka's HTML to PDF converter renders with the browser's own engine (so your CSS is interpreted faithfully), and below is the full diagnostic list, in order of how often each one is the problem.

Cause 1 (most common): external resources don't load

By a wide margin the top cause: your HTML links its styles, fonts, or images by URL (<link rel="stylesheet" href="...">, @font-face with a remote src, <img src="https://...">), and the converter cannot or will not fetch them. Many server-side and security-conscious converters do not make outbound network requests, so every externally-linked asset silently vanishes and you get raw, unstyled HTML.

Fix: embed everything into the HTML.

  • Move CSS from external files into a <style> block in the <head> (or inline it).
  • Embed fonts as Base64 data URIs inside @font-face instead of remote src.
  • Embed images as Base64 data URIs, or use local paths the converter can actually reach.

Once the HTML is self-contained, there is nothing external to fetch and the styling holds. This single change resolves the large majority of "PDF is unstyled" reports.

Why this matters especially for a privacy-focused converter: a tool that runs locally and makes no network requests (the same property that means your file is never uploaded) also, by design, will not reach out to pull a remote stylesheet or font. That is a deliberate security boundary, not a bug: fetching arbitrary external URLs from a document you are converting is exactly the behavior that enables tracking and SSRF attacks. So with PDFMoka's HTML to PDF tool, the rule is the same, self-contained HTML (inlined CSS, embedded assets) renders faithfully, while externally-linked resources will not load. For the underlying "what loads and what doesn't" boundary, this is the trade you make for a converter that never phones home.

Cause 2: no print styles, or print styles hiding content

CSS can define separate rules for screen and print via @media print. Two failure modes:

  • Your layout relies on screen styles that were never carried into print context.
  • A @media print block (yours, or one injected by a framework) hides elements with display: none, so they vanish from the PDF.

Fix: add or audit your @media print rules. Put print-specific layout there, and check nothing important is being hidden:

@media print {
  /* keep your real layout; don't hide content you need */
  .sidebar, .nav { display: none; }   /* only hide chrome, not content */
}

Cause 3: background colors and images stripped

Browsers drop background colors and images when printing by default (the "economy" print mode) to save ink. If your design depends on colored backgrounds, they disappear.

Fix: declare print-color-adjust: exact on the relevant elements and enable "Background graphics" in the print dialog, both are required. This is the same mechanism covered in depth in print code with syntax highlighting; the fix is identical for any colored HTML.

Cause 4: viewport units and responsive layout

Units like vw, vh, and layouts tuned to a screen width render against the converter's page width, not your screen, so 100vw columns collapse or overflow.

Fix: in @media print, replace viewport-relative units with absolute ones (mm, cm, pt, px). To preview A4 width in a browser, test around 794px wide.

Cause 5: unsupported CSS features

Some modern CSS has no PDF equivalent in certain engines: backdrop-filter (frosted glass), some filters, blend modes, and sticky positioning commonly render wrong or not at all. Chromium-based rendering (what a browser print or a browser-based tool uses) supports the most; lighter converters support less.

Fix: provide static fallbacks inside @media print (for example a solid rgba background instead of backdrop-filter: blur()). Using a Chromium-based converter also minimizes this class of problem, since it renders the same engine your browser does.

Cause 6: JavaScript-applied styles

If your styling is applied by JavaScript after load (runtime theme switching, some CSS-in-JS), a converter that does not execute JavaScript will miss it.

Fix: either bake the final styles into static CSS, or use a converter that runs JavaScript (a headless-browser or browser-based tool) so the post-load styles are present at render time.

Diagnostic checklist (in priority order)

  1. External CSS/fonts/images? Inline them, this fixes most cases.
  2. @media print present and not hiding content?
  3. Background colors gone? print-color-adjust: exact + Background graphics on.
  4. vw/vh units? Swap for absolute units in print.
  5. Fancy CSS (backdrop-filter, blend modes)? Add static fallbacks.
  6. JS-applied styles? Bake them in, or use a JS-executing converter.

Work top to bottom; the first two items resolve the majority of unstyled-PDF cases. For converting a local HTML file cleanly, see how to convert an HTML file to PDF locally.

References