How to Convert HTML to PDF (Preserve CSS Styling)
Why HTML-to-PDF Conversions Go Wrong
Anyone who has fought a misbehaving PDF export knows the pain. You convert an HTML file, and the result is a mess of broken layouts, missing fonts, or a page that looks nothing like your browser preview. The problem isn't the concept; it's the execution. PDF renderers vary wildly in how they interpret CSS, and most generic converters simply strip or ignore stylesheets unless you force their hand. The fundamental conflict is between HTML's flow-based model and PDF's page-based model. Web content expands and contracts to fit a viewport. A PDF page has fixed dimensions. No scrolling, no dynamic reflow. Bridging these two worlds requires a renderer that understands CSS page rules, properly handles embedded fonts, and respects modern layouts like flexbox and grid. Many tools just don't. Common failures are depressingly predictable: Google Fonts don't load because the converter runs offline; background colors vanish because the renderer defaults to a 'print mode' that strips them to save ink; multi-column layouts collapse into a single, sad stack. Knowing these pitfalls is half the battle. This guide will walk you through avoiding them, whether you're using CocoConvert's [HTML to PDF tool](/convert/html-to-pdf) or building your own workflow.
What 'Preserving CSS Styling' Actually Means
Before diving into solutions, let's get precise about what 'preserving CSS' even means. Styling in a PDF context isn't a single thing; it’s four distinct categories, and not all of them survive every conversion method. **Visual styling** is the most fragile. This includes colors, borders, box shadows, and background images. Print renderers often suppress backgrounds by default to save ink. In Chrome's own print dialog, for instance, you have to dig into 'More settings' and check 'Background graphics' or your backgrounds will simply disappear. **Typography**—font family, weight, size, line-height—lives or dies based on font availability. If your fonts are referenced by a remote URL, any converter that doesn't fetch external resources will fall back to system defaults. Your beautiful Inter or Lato typeface instantly becomes a dreary Times New Roman. The only surefire way to preserve fonts is to embed them. **Layout** is where things get truly complicated. Modern CSS features like flexbox, CSS Grid, and absolute positioning are handled well by Chromium-based renderers. But older engines like wkhtmltopdf (which uses a WebKit engine from around 2013) will mangle modern layouts in predictable, frustrating ways. **Page-specific CSS** like `@page` rules, `page-break-before`, and `break-inside: avoid` is actually better supported in PDF conversion than in browsers. This CSS exists specifically for paged media. By using `@media print` blocks, you can create styles that only apply to the PDF version, giving you fine-grained control without messing up your website's appearance. Knowing which category your styling issue falls into tells you which tools and techniques are likely to fix it.
Using CocoConvert to Convert HTML to PDF
CocoConvert's [HTML to PDF converter](/convert/html-to-pdf) runs on a modern Chromium-based rendering engine. This means it handles contemporary CSS—including flexbox, Grid, CSS variables, and `calc()` values—with high fidelity. Here’s how to get perfect results. **Step 1: Prepare your HTML file.** If your styles are in an external stylesheet, you have two options: either inline them with a library like Juice, or ensure the stylesheet path is relative and included in your upload. CocoConvert processes a single HTML file at a time and does not fetch remote URLs. Google Fonts or CDN-hosted stylesheets will not load. **Step 2: Embed your fonts.** This is non-negotiable for custom typography. Convert your font files to base64 and embed them directly in a `<style>` block using `@font-face`. Yes, this increases file size, but it is the only way to guarantee your fonts render correctly. For a typical body font with regular and bold weights, this might add 80–150 KB to your HTML file. **Step 3: Upload and set page options.** Once uploaded, CocoConvert presents options for page size (A4, Letter, Legal, or custom dimensions), orientation, and margins. A4 with 15mm margins on all sides is a solid default. If you're converting a wide dashboard or table, switch to landscape orientation. **Step 4: Enable background graphics.** This is the single most common mistake. In CocoConvert’s options panel, you must toggle 'Print backgrounds' to On. If you don't, any element with a `background-color` or `background-image` will render as plain white. **Step 5: Download and verify.** Don't just glance at the PDF in your browser. Open it in a proper viewer like Adobe Acrobat Reader and check that fonts are correctly embedded by going to File > Properties > Fonts. Every font in the list should say 'Embedded Subset' next to it.
Handling the Limitations: What CocoConvert Can't Do
Let's be honest about what CocoConvert is not. It's a powerful general-purpose converter, but certain tasks are outside its scope. Knowing these limitations upfront will save you from troubleshooting dead ends. **JavaScript-rendered content.** If your page is built by a framework like React or Vue, uploading the source HTML file won't work. The converter sees the static HTML, not the final page built by JavaScript. For JS-heavy pages, your best bet is to first save the fully rendered HTML from your browser (right-click > Save As > Webpage, Complete) and upload that file. Alternatively, you'd need a headless browser tool like Puppeteer. **Interactive elements.** Forms, dropdowns, and hover states are not interactive in a PDF. The conversion captures a static snapshot of the element's default state. If an accordion is closed when the page is rendered, it will be closed in the PDF. There's no way around this; it's the nature of PDF. **Very large files.** CocoConvert has a 50 MB file limit on the free tier and 200 MB on paid plans. This sounds generous, but an HTML file with numerous base64-encoded images can hit these limits surprisingly quickly. A single high-resolution PNG can easily add 3–5 MB to the file size. **Complex SVG animations.** Static SVGs render beautifully. However, any CSS or SMIL animations inside an SVG will be frozen at their initial frame. CocoConvert is built for straightforward, file-based conversion. When you have a finished HTML document and need a reliable PDF, it's the right tool. For complex, server-side pipelines that require executing JavaScript, you'll need to look at programmatic tools like Playwright or Puppeteer.
CSS Techniques That Make PDF Output Cleaner
You can save yourself a world of pain by writing CSS with PDF output in mind from the start. Fixing problems after the fact is always harder. **Use `@media print` for PDF-specific overrides.** This is your secret weapon. Wrap any PDF-only rules in a `@media print` block to hide elements like navigation bars, remove box shadows that look muddy in print, or adjust font sizes for readability on a page. For example: ```css @media print { nav, .sidebar { display: none; } body { font-size: 11pt; } .card { box-shadow: none; border: 1px solid #ddd; } } ``` **Control page breaks explicitly.** Don't let the renderer decide where to break pages. Use `break-before: page` to force a new PDF page before a major section, and apply `break-inside: avoid` to elements like tables and figures to prevent them from splitting awkwardly across two pages. This is absolutely essential for professional-looking reports. **Set explicit `@page` dimensions.** If you know the target page size, declare it in your CSS. This prevents mismatches between your styles and the converter's settings, which can cause unexpected text clipping. ```css @page { size: A4 portrait; margin: 15mm 20mm; } ``` **Avoid viewport units in print layouts.** Units like `vw` and `vh` are meaningless for a fixed PDF page. For elements that need to span the page, use `mm`, `pt`, or percentages instead. **Test with Chrome's built-in print preview first.** Before you upload anything, hit Ctrl+P (or Cmd+P) and select 'Save as PDF'. This gives you an instant preview using the same Chromium engine that powers CocoConvert. It's the fastest way to iterate on your CSS without wasting time on repeated uploads.
Converting a Full Webpage (URL) vs. an HTML File
The approach for converting a local HTML file is fundamentally different from converting a live webpage URL. You need to pick the right tool for the right job. **Converting a local HTML file** is what CocoConvert's [HTML to PDF tool](/convert/html-to-pdf) excels at. This method requires a self-contained document. All CSS must be inlined or in a `<style>` block, all images must be base64-encoded or referenced via relative paths in a ZIP file, and fonts must be embedded. Think of it as mailing a sealed package: everything the renderer needs must be inside from the start. This makes the process incredibly reliable. **Converting a live webpage by URL** is a different beast entirely. It demands a tool that can spin up a real browser session, navigate to the URL, wait for JavaScript to execute and web fonts to download, and then print to PDF. Tools like Puppeteer, Playwright, or services like Browserless.io are designed for this. The tradeoff is a mountain of complexity. You have to contend with authentication, cookie pop-ups, lazy-loaded content, and unpredictable network speeds. For most common tasks—generating PDF invoices from a template, exporting a report, or archiving a styled document—the file-based approach is simpler and far more predictable. You control the input completely, so the output is consistent. If you are building a system that generates PDFs from live user data, the best practice is a hybrid approach: populate an HTML template on your server with the user's data, and then pass that fully-rendered HTML string to a conversion API. CocoConvert's API supports this workflow, accepting HTML directly in a POST request.
Verifying the Output: A PDF Quality Checklist
Just because a PDF looks right on your screen doesn't mean it's ready. Before you send that file to a client or publish it, run through this quick but critical checklist. **Fonts embedded?** Open the PDF in Adobe Acrobat Reader and navigate to File > Properties > Fonts. Every font you used should be listed with 'Embedded Subset'. If a font isn't embedded, it will be replaced by a system default on any machine that doesn't have it installed, ruining your design. **Colors accurate?** Web CSS uses the RGB color space. Most PDFs destined for screens are fine in RGB. However, if the PDF is intended for commercial printing, it may require a CMYK color space, which is a separate conversion step that happens after the initial HTML-to-PDF process. **Text selectable and searchable?** Try to click and drag to select a line of text. If you can, the text is real vector text, which is good for searchability and accessibility. If you can't select it, the converter may have rasterized the page into a flat image—a disaster for copy-paste, screen readers, and text search. **Page count and breaks correct?** Quickly scroll through every page. Are there any headings orphaned at the bottom of a page? Are tables or charts split in awkward places? Are figures separated from their captions? **File size reasonable?** A ten-page, text-heavy PDF should be well under 1 MB. If it's 15 MB, something is wrong. The culprit is usually uncompressed images or an accidental rasterization of the entire page. **Hyperlinks functional?** Click on any links in the document. A good converter preserves `<a href>` tags as clickable links in the final PDF. CocoConvert does this by default, but it's always worth checking. Spending three minutes on these six checks will catch 95% of conversion problems before they can cause trouble for someone else. It's a final polish that separates professional output from amateur results.