Question
Converting HTML and CSS to PDF in PHP: What to Expect and Common Approaches
Question
I have an HTML document (not XHTML) that renders correctly in Firefox 3 and IE 7. It uses fairly basic CSS, and the page displays as expected in the browser.
I now need to convert that HTML into a PDF.
I have already tried several tools:
- DOMPDF: It had major problems with tables. After simplifying some large nested tables, memory usage improved, but table rendering was still incorrect and images were not handled reliably.
- HTML2PDF / HTML2PS: These worked better in some cases. Some images rendered, and table formatting was improved, but the conversion failed with
unknown node_type()errors. - HTMLDOC: This worked for very basic HTML, but CSS support was extremely limited, so it was not suitable.
I also tried a Windows application called Html2Pdf Pilot, which produced better results, but I need a solution that at least runs on Linux and ideally can be triggered on demand from PHP on the web server.
What is the main concept I am missing here, and what practical approaches are available when converting HTML and CSS to PDF from a PHP-based system?
Short Answer
By the end of this page, you will understand why converting HTML and CSS to PDF is harder than it first appears, why browser rendering does not automatically match PDF rendering, and how PHP applications usually solve this problem in practice. You will also learn the trade-offs between HTML-to-PDF libraries, browser-based renderers, and template simplification.
Concept
HTML and CSS are designed primarily for screen rendering in browsers, while PDF is a fixed-layout document format designed for consistent printing and sharing. That difference is the key reason HTML-to-PDF conversion can be difficult.
A browser like Firefox or Chrome has a powerful rendering engine that understands a huge amount of HTML, CSS, fonts, images, layout rules, and JavaScript behavior. Many PDF libraries do not implement the full browser layout engine. Instead, they support only a subset of HTML and CSS.
That means:
- A page that looks correct in a browser may render badly in a PDF tool.
- Complex tables, nested layouts, floats, positioning, and external images can fail.
- CSS support varies a lot between tools.
- Memory usage can become a problem for large documents.
In PHP projects, there are usually three broad strategies:
-
Use a PHP HTML-to-PDF library
- Good for simple invoices, reports, receipts, and basic tables.
- Often limited CSS support.
- Easier to integrate directly into PHP.
-
Use a real browser engine to print to PDF
- Usually gives much better HTML/CSS support.
- Better for modern layouts.
- Often done with headless Chrome or a wrapper service.
-
Generate PDF with a PDF library directly
- Instead of converting HTML, you manually place text, images, and tables.
- More work, but highly reliable for structured documents.
This matters in real programming because PDF generation is common for:
- invoices
- shipping labels
- account statements
- reports
- certificates
Mental Model
Think of HTML-to-PDF conversion like asking two different artists to draw the same page.
- A web browser is an artist trained to paint flexible, responsive screens.
- A PDF renderer is an artist trained to produce fixed, printable pages.
Even if both artists get the same instructions, they may interpret them differently.
If your HTML is very simple, both artists produce similar results. But if your page uses complicated layout rules, nested tables, external images, or advanced CSS, the PDF artist may struggle unless it has a browser-quality engine.
So the real lesson is:
- Browser rendering is not the same as PDF rendering.
- The more complex your HTML, the more important the rendering engine becomes.
Syntax and Examples
A common beginner approach in PHP is to pass an HTML string into an HTML-to-PDF library.
<?php
require 'vendor/autoload.php';
use Dompdf\Dompdf;
$html = '
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
h1 { color: #333; }
table { border-collapse: collapse; width: 100%; }
td, th { border: 1px solid #999; padding: 8px; }
</style>
</head>
<body>
<h1>Sales Report</h1>
<table>
<tr><th>Item</th><th>Total</th></tr>
<tr><td>Books</td><td>$120</td></tr>
<tr><td>Pens</td><td>$45</td></tr>
</table>
</body>
</html>';
$dompdf = new Dompdf();
$dompdf->loadHtml($html);
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
$dompdf->stream('report.pdf');
This works well for simple documents.
What this example demonstrates
- HTML is created as a string.
- CSS is embedded in a
<style>block. - The library parses the HTML and tries to render it into a PDF.
- A PDF is sent to the browser.
Important limitation
Step by Step Execution
Consider this small PHP example:
<?php
require 'vendor/autoload.php';
use Dompdf\Dompdf;
$html = '<h1>Hello PDF</h1><p>This is a test.</p>';
$pdf = new Dompdf();
$pdf->loadHtml($html);
$pdf->setPaper('A4', 'portrait');
$pdf->render();
$output = $pdf->output();
file_put_contents('example.pdf', $output);
Here is what happens step by step:
-
require 'vendor/autoload.php';- Loads Composer dependencies so PHP can find the PDF library.
-
use Dompdf\Dompdf;- Imports the
Dompdfclass into the file.
- Imports the
Real World Use Cases
HTML-to-PDF conversion is widely used when an application already has data shown on a web page and needs a downloadable document version.
Common examples
- Invoices: Convert order details into printable PDFs.
- Reports: Export sales summaries, analytics, or audit results.
- Receipts: Generate payment confirmations.
- User statements: Monthly account summaries or billing history.
- Certificates: Produce fixed-layout documents with branding.
- Admin exports: Turn dashboard views into shareable PDFs.
When simple HTML-to-PDF works well
It usually works best for documents that are:
- mostly text
- basic tables
- limited styling
- fixed page widths
- predictable in length
When it becomes difficult
Problems often appear when the source HTML includes:
- responsive layouts meant for browsers
- advanced CSS features
- JavaScript-generated content
- large nested tables
- remote images with access restrictions
- custom fonts without proper embedding
Real Codebase Usage
In real codebases, developers usually do not send arbitrary website pages straight into a PDF converter and hope for perfect results. Instead, they use a few practical patterns.
1. Separate PDF templates from web templates
A screen page and a PDF page often need different HTML.
- Screen templates can be responsive and interactive.
- PDF templates should be simpler and fixed-width.
Example pattern:
if ($format === 'pdf') {
include 'templates/invoice-pdf.php';
} else {
include 'templates/invoice-web.php';
}
2. Use guard clauses for missing assets
Remote images, fonts, or data may fail.
if (empty($invoiceItems)) {
throw new RuntimeException('Cannot generate PDF without invoice items.');
}
3. Preprocess data before rendering
Instead of doing logic inside HTML, prepare everything first.
$total = array_sum(array_column($items, ));
Common Mistakes
Here are common beginner mistakes when converting HTML to PDF.
1. Expecting browser-perfect rendering
A page working in Firefox or Chrome does not guarantee that a PDF library can render it the same way.
How to avoid it
- Check the library's supported HTML/CSS features.
- Test with a simplified template first.
2. Reusing complex web layouts
Broken example:
<div class="page">
<div class="sidebar">...</div>
<div class="content">...</div>
</div>
If the PDF engine has weak layout support, this may break.
Better approach
Use a simpler, print-focused layout.
3. Using deeply nested tables for layout
Broken idea:
<table>
<tr>
<td>
<>
Too much nesting
Comparisons
Here is a practical comparison of the main approaches.
| Approach | Strengths | Weaknesses | Best for |
|---|---|---|---|
| PHP HTML-to-PDF library | Easy to call from PHP, simple deployment | Limited CSS support, struggles with complex layouts | Invoices, receipts, simple reports |
| Browser-based PDF rendering | Better HTML/CSS support, closer to real browser output | More system setup, heavier runtime | Modern layouts, branded reports |
| Direct PDF generation library | Reliable output, precise control | More manual coding, less reusable HTML | Structured documents with fixed layouts |
HTML-to-PDF library vs browser engine
| Feature | HTML-to-PDF Library | Browser Engine |
|---|---|---|
| CSS support |
Cheat Sheet
// Basic PHP HTML-to-PDF flow
$pdf = new Dompdf();
$pdf->loadHtml($html);
$pdf->setPaper('A4', 'portrait');
$pdf->render();
$pdf->stream('file.pdf');
Quick rules
- Browsers and PDF engines do not render HTML the same way.
- Simple HTML and CSS are more reliable than complex layouts.
- Tables for data are usually fine; nested tables for layout are risky.
- Remote images may require special configuration.
- Large documents can hit memory limits.
- A separate PDF template is often better than reusing the web page template.
Good practices
- Keep PDF HTML simple.
- Use fixed widths when needed.
- Test with realistic data.
- Log rendering errors.
- Save generated output during debugging.
Warning signs
- Broken tables
- Missing images
- Incorrect page breaks
- Memory exhaustion
- CSS rules being ignored
If you need higher accuracy
Use a browser-based PDF renderer instead of a limited HTML-to-PDF library.
FAQ
Why does my HTML look correct in the browser but wrong in the PDF?
Because many PDF tools support only part of HTML and CSS. Browsers have much more powerful rendering engines.
Can PHP convert any HTML page into a perfect PDF?
Not reliably. Simple pages often work, but complex layouts, advanced CSS, and JavaScript can cause differences.
Why do tables often break in HTML-to-PDF conversion?
Tables are hard to lay out across fixed PDF pages, especially when they are nested, wide, or heavily styled.
Why are my images missing from the generated PDF?
The converter may not support remote images by default, the URL may be inaccessible, or permissions/configuration may block loading.
Should I reuse my website page as the PDF template?
Usually not for anything complex. A simpler PDF-specific template is often more stable.
When should I use a browser-based PDF solution?
Use it when you need better CSS support, closer visual matching to the browser, or more complex layouts.
Is direct PDF generation better than HTML conversion?
For highly structured documents, yes. It gives more control and reliability, but requires more manual layout code.
Mini Project
Description
Build a simple invoice PDF generator in PHP. The project demonstrates a practical use of HTML-to-PDF conversion with a layout that is intentionally simple and PDF-friendly. This helps you see how to structure HTML for reliable PDF output instead of trying to convert a full browser-oriented page.
Goal
Generate a basic invoice PDF from PHP using simple HTML, CSS, and tabular data.
Requirements
- Create a PHP script that builds an invoice as an HTML string.
- Include a heading, customer name, and a table of invoice items.
- Calculate and display the total amount.
- Convert the HTML into a PDF and save it to a file.
- Keep the HTML layout simple and avoid nested tables.
Keep learning
Related questions
Angular ngClass Conditional Class Binding Explained
Learn how to use Angular ngClass for conditional classes, fix common binding mistakes, and understand why this template error happens.
CSS :not() Selector for Elements Without a Class or Attribute
Learn how to use the CSS :not() selector to target elements that do not have a specific class or attribute, with examples and common pitfalls.
CSS Font Scaling Relative to Container Size: %, em, rem, vw, and Responsive Text
Learn how CSS font scaling really works and how to make text responsive using %, em, rem, vw, clamp(), and media queries.