Skip to content
Back to Blog
how-to-convert

How to Convert HTML to PDF (Preserve CSS Styling)

2026-05-17 9 min read

Why HTML-to-PDF Conversions Go Wrong

If you've ever exported an HTML file to PDF and ended up with broken layouts, missing fonts, or a page that looks nothing like your browser preview, you're not alone. The problem isn't the concept — it's the execution. PDF renderers vary wildly in how they interpret CSS, and most generic converters strip or ignore stylesheets entirely unless you explicitly tell them not to. The core issue is that HTML is a flow-based format. Content expands and contracts to fit the viewport. PDF, by contrast, is page-based — fixed dimensions, no scrolling, no dynamic reflow. Bridging those two models requires a renderer that understands CSS page rules, handles embedded fonts, and respects things like flexbox and grid layouts. Many tools simply don't. Common failure points include: Google Fonts not loading because the converter runs offline, background colors disappearing because the renderer defaults to 'print mode' (which strips backgrounds to save ink), and multi-column layouts collapsing into a single stack. Knowing these pitfalls before you start will save you hours of trial and error. This guide walks through how to avoid them — whether you're using CocoConvert's [HTML to PDF tool](/convert/html-to-pdf) or setting up a workflow of your own.

What 'Preserving CSS Styling' Actually Means

Before getting into steps, it helps to be precise about what you're trying to preserve. CSS styling in a PDF context breaks into four distinct categories, and not all of them survive every conversion method. **Visual styling** — colors, borders, box shadows, background images — is the most fragile. Print renderers often suppress backgrounds by default. In Chrome's print dialog, for example, you need to check 'Background graphics' under 'More settings' or backgrounds will vanish entirely. **Typography** — font family, weight, size, line-height — depends on whether your fonts are embedded or referenced via a remote URL. A converter that doesn't fetch external resources will fall back to system fonts, so your carefully chosen Inter or Lato typeface becomes Times New Roman. **Layout** — flexbox, CSS Grid, absolute positioning — is where things get genuinely complicated. Chromium-based renderers handle modern CSS layout well. Older engines like wkhtmltopdf (which uses the Qt WebKit engine, roughly equivalent to Safari circa 2013) will misrender flexbox in predictable, frustrating ways. **Page-specific CSS** — `@page` rules, `page-break-before`, `break-inside: avoid` — is actually supported better in PDF conversion than in browsers, because it exists specifically for print output. Using `@media print` blocks in your CSS lets you fine-tune what the PDF looks like without affecting the web version. Knowing which category your styling falls into tells you immediately which tools are likely to work.

Using CocoConvert to Convert HTML to PDF

CocoConvert's [HTML to PDF converter](/convert/html-to-pdf) uses a Chromium-based rendering engine, which means it handles modern CSS — including flexbox, Grid, CSS custom properties (variables), and `calc()` values — reliably. Here's exactly how to get the best results. **Step 1: Prepare your HTML file.** If your styles are in an external stylesheet, either inline them using a tool like Juice (a Node.js library that inlines CSS) or make sure the stylesheet path is relative and included in the same upload. CocoConvert accepts a single HTML file upload; it does not fetch remote URLs during conversion, so Google Fonts or CDN-hosted stylesheets won't load. **Step 2: Embed your fonts.** Convert your font files to base64 and embed them directly in a `<style>` block using `@font-face`. This adds file size but guarantees the font renders correctly. For a typical body font at two weights, expect to add roughly 80–150 KB to your HTML file. **Step 3: Upload and set page options.** After uploading, CocoConvert gives you options for page size (A4, Letter, Legal, or custom dimensions in mm), orientation (portrait or landscape), and margins. For most documents, A4 with 15mm margins on all sides is a safe starting point. If you're converting a dashboard or wide table, switch to landscape. **Step 4: Enable background graphics.** This is the setting most people miss. In CocoConvert's options panel, toggle 'Print backgrounds' to On. Without this, any element with a `background-color` or `background-image` will render as white. **Step 5: Download and verify.** Open the PDF in Adobe Acrobat Reader (not just a browser PDF viewer) and check that fonts are embedded — go to File > Properties > Fonts tab. Every font should list 'Embedded Subset' next to it.

Handling the Limitations: What CocoConvert Can't Do

Honesty matters here. CocoConvert is a solid general-purpose converter, but there are specific scenarios where it will fall short, and you should know them upfront rather than waste time troubleshooting. **JavaScript-rendered content.** If your HTML page relies on JavaScript to build the DOM — a React or Vue app, for instance — uploading the raw HTML file won't work. The converter processes the static HTML; it doesn't execute JavaScript. For JS-heavy pages, you need to either export the fully rendered HTML from your browser (right-click > Save As > Webpage, Complete) or use a headless browser tool like Puppeteer, which can wait for JavaScript execution before capturing the page. **Interactive elements.** Forms, dropdowns, accordions, and hover states don't translate to PDF. What you get is a snapshot of the element's default state. If a dropdown is closed when the conversion runs, it will be closed in the PDF. **Very large files.** CocoConvert handles files up to 50 MB on the free tier and 200 MB on paid plans. An HTML file with many embedded base64 images can hit these limits faster than you'd expect. A single high-resolution PNG embedded as base64 can be 3–5 MB on its own. **Complex SVG animations.** Static SVGs render fine. CSS or SMIL animations within SVGs will be frozen at their initial state. For Puppeteer-based workflows or server-side rendering pipelines, CocoConvert isn't the right tool — and that's fine. It's designed for straightforward, file-based conversion where you have a finished HTML document and need a reliable PDF output.

CSS Techniques That Make PDF Output Cleaner

Regardless of which converter you use, writing CSS with PDF output in mind from the start produces dramatically better results than trying to fix problems after the fact. **Use `@media print` for PDF-specific overrides.** Wrap any PDF-specific rules in a `@media print` block. Common uses: hiding navigation bars, removing box shadows (which can look muddy in PDF), and adjusting font sizes. Example: ```css @media print { nav, .sidebar { display: none; } body { font-size: 11pt; } .card { box-shadow: none; border: 1px solid #ddd; } } ``` **Control page breaks explicitly.** Use `break-before: page` to force a new PDF page before a section heading, and `break-inside: avoid` on elements like tables, figures, or callout boxes to prevent them from splitting across pages. This is particularly important for multi-page reports. **Set explicit `@page` dimensions.** If you know the output page size, declare it: ```css @page { size: A4 portrait; margin: 15mm 20mm; } ``` This ensures the document's own CSS agrees with whatever page size you've selected in the converter settings — mismatches here cause unexpected text clipping. **Avoid viewport units in print layouts.** `vw` and `vh` units are relative to the browser viewport, not the PDF page. Replace them with `mm`, `pt`, or percentage values for elements that need to span the page width. **Test with Chrome's built-in print preview first.** Before uploading to any converter, use Chrome's Ctrl+P (or Cmd+P on Mac) print dialog and select 'Save as PDF'. This gives you an instant preview using the same Chromium engine CocoConvert uses, letting you iterate on CSS quickly without repeated uploads.

Converting a Full Webpage (URL) vs. an HTML File

There's an important distinction between converting a local HTML file and converting a live webpage, and it changes your approach significantly. **Converting a local HTML file** (what CocoConvert's [HTML to PDF tool](/convert/html-to-pdf) is designed for) requires self-contained HTML. All CSS must be inlined or in a `<style>` block, all images must be base64-encoded or referenced by relative paths within a ZIP upload, and fonts must be embedded. Think of it as sending a sealed envelope — everything the renderer needs has to be inside. **Converting a live webpage by URL** requires a different tool category — one that opens a real browser session, navigates to the URL, waits for the page to fully load (including JS execution and web fonts), and then prints to PDF. Tools like Puppeteer, Playwright, or services like Browserless.io are built for this. The trade-off is complexity: you need to handle authentication, cookie consent banners, lazy-loaded images, and variable load times. For most use cases — generating PDF invoices from an HTML template, exporting a report, archiving a styled document — the file-based approach is simpler and more predictable. You control exactly what goes in, so you know exactly what comes out. If you're building a pipeline that generates PDFs from live user data (e.g., generating a personalized PDF for each customer), the typical architecture is: populate an HTML template server-side with the user's data, then pass that rendered HTML string to a conversion API. CocoConvert offers an API endpoint for this workflow, which accepts HTML as a POST body rather than requiring a file upload.

Verifying the Output: A PDF Quality Checklist

A PDF that looks right on screen isn't necessarily correct. Before sending a converted PDF to a client or publishing it, run through this checklist. **Fonts embedded?** Open the PDF in Adobe Acrobat Reader, go to File > Properties > Fonts. Every font should show 'Embedded Subset'. If any font shows 'Not Embedded', it will render differently on machines that don't have that font installed — which is most of them. **Colors accurate?** PDFs can use RGB or CMYK color spaces. Web CSS uses RGB. Most screen-destined PDFs are fine in RGB, but if the PDF is going to a commercial printer, you may need CMYK conversion, which is a separate step beyond HTML-to-PDF conversion. **Text selectable and searchable?** Click on body text in the PDF viewer. If you can select it, the text is real text (good for searchability and accessibility). If it's not selectable, the converter may have rasterized the page into an image, which means no copy-paste, no screen readers, no text search. **Page count and breaks correct?** Scroll through every page and check that headings aren't orphaned at the bottom of a page, tables haven't been split in awkward places, and figures are paired with their captions. **File size reasonable?** A 10-page text-heavy PDF should be under 1 MB. If it's 15 MB, something was rasterized that shouldn't have been, or you have uncompressed images. Excessive file size causes problems with email attachments and slow downloads. **Hyperlinks functional?** Click any links in the PDF. A good converter preserves `<a href>` elements as clickable PDF links. If links are dead, check whether the converter has a 'preserve hyperlinks' option — CocoConvert enables this by default. Running through these six checks takes about three minutes and catches 95% of conversion problems before they reach anyone else.

Ready to convert?

Try it now — fast, secure, and private.

Convert Now →
How to Convert HTML to PDF (Preserve CSS Styling) | CocoConvert Blog