Skip to content
getnextpdf.com

HTML to PDF, the easy path

So far in this track you have built pages one call at a time. Many documents are quicker to describe as markup, the tag-based text format used for web pages. In this tutorial you hand NextPDF some Hypertext Markup Language (HTML), and the engine draws the page for you.

A one-page report rendered from a single HTML string. It has a colored heading, a short paragraph, and a table with a totals row. You style it with Cascading Style Sheets (CSS), the rule language that controls how markup looks. In the earlier tutorials you used the fluent Application Programming Interface (API), the chained method calls. Here you describe the layout in markup instead, and the same engine renders it.

Create a file named 01-html.php in your project folder, next to vendor. Paste in this complete script:

<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
@mkdir(__DIR__ . '/out');
$document = Document::createStandalone();
$document->setTitle('Monthly reading report');
$document->addPage();
$html = <<<'HTML'
<h1 style="color: #1E3A8A;">Monthly reading report</h1>
<p>This report was rendered from <strong>HTML</strong> with inline
<em>CSS</em>. The table below lists two books and their page counts.</p>
<table border="1" cellpadding="5" cellspacing="0" style="width: 100%;">
<thead>
<tr style="background-color: #1E3A8A; color: #FFFFFF;">
<th style="width: 55%;">Title</th>
<th style="width: 20%; text-align: center;">Format</th>
<th style="width: 25%; text-align: right;">Pages</th>
</tr>
</thead>
<tbody>
<tr>
<td>The Paper Trail</td>
<td style="text-align: center;">Hardcover</td>
<td style="text-align: right;">312</td>
</tr>
<tr style="background-color: #F8FAFC;">
<td>Ink and Bytes</td>
<td style="text-align: center;">Paperback</td>
<td style="text-align: right;">248</td>
</tr>
</tbody>
<tfoot>
<tr style="font-weight: bold;">
<td colspan="2" style="text-align: right;">Total pages:</td>
<td style="text-align: right;">560</td>
</tr>
</tfoot>
</table>
HTML;
$document->writeHtml($html);
$document->save(__DIR__ . '/out/reading-report.pdf');
echo "Wrote out/reading-report.pdf\n";

Run the script from the project folder:

Terminal window
php 01-html.php

You should see one line of output:

Wrote out/reading-report.pdf

Open out/reading-report.pdf in any Portable Document Format (PDF) viewer. The heading is dark blue, and the table header row is filled with the same color.

  • @mkdir(__DIR__ . '/out'); creates the output folder. The @ sign hides the warning when the folder already exists, so repeat runs stay quiet.
  • Document::createStandalone(), setTitle(), and addPage() work exactly as in the earlier tutorials. Switching to markup changes nothing about document setup.
  • writeHtml() reads your string once, from top to bottom, and draws each element at the current position. Headings and paragraphs become styled text. The table becomes measured rows of bordered cells.
  • The inline style attributes carry the CSS. The engine understands common properties such as color, background-color, text-align, and width.
  • No browser and no extra software are involved. The pipeline is plain PHP inside the engine, so the script runs wherever your Composer install runs.

The engine supports a practical subset of HTML and CSS, not everything a browser accepts. Anything outside that subset is skipped quietly rather than raising an error. The CSS support matrix records exactly what is covered. For a deeper walk through this pipeline, see Render HTML to a PDF page.

When to use HTML and when to use the fluent API

Section titled “When to use HTML and when to use the fluent API”

Both routes run on the same engine, so pick whichever fits the document.

  • Choose writeHtml() when the document reads like a web page: headings, paragraphs, lists, and tables. Markup is faster to write and easier for teammates to edit.
  • Choose the fluent API when you need exact placement, such as fixed positions or precisely measured cells. Markup gives you flow; the fluent calls give you control.
  • Check the CSS support matrix before relying on a property. When a style is not covered, build that part with fluent calls instead.

Real HTML often comes from outside your code, for example from a form or a database. Treat it as untrusted input, and validate or clean it before rendering. By default, the built-in pipeline runs no scripts and fetches no remote resources. That default keeps the renderer conservative even when the markup is not. If you need browser-grade rendering options, see Choose your path.

  • Failed to open stream: No such file or directory usually means the script cannot find vendor/autoload.php. Run it from the folder where you ran Composer.
  • A missing style is usually a property outside the supported subset. The engine skips what it does not support instead of failing. Compare your markup against the CSS support matrix.
  • An exception while rendering names the exact problem. Look it up in the rendering and input/output errors reference.

For anything else, start with the troubleshooting guide.

You can now build documents call by call and from markup. Finish the track with Where to go next. It maps the cookbook, the reference, and the guides you will use after this track.