Migrating an HTML to PDF integration from Classic to Next
The class is still called HtmlToPdfConverter and the shape of a conversion — create, set options, call ConvertUrl or ConvertHtml — is the same. What changes is the rendering engine behind it, and with it the way the PDF page is sized and the way headers and footers are described. This guide lists the differences you will actually hit, with the Classic and Next code side by side. Your existing HTML to PDF license covers both editions.
What stays the same
The conversion calls
ConvertUrl(url),ConvertHtml(html, baseUrl), the…ToFilevariants- One converter instance per conversion
ConversionDelay,NavigationTimeout
The option groups
HtmlViewerWidth,HtmlViewerHeight,HtmlViewerZoomPdfDocumentOptionswithPdfPageSize,PdfPageOrientation, margins in points- Security, viewer preferences, digital signatures
Licensing
- The HTML to PDF license and the Toolkit license cover Classic and Next
- Same key, set in a different place (see below)
- Demo mode without a key, with watermarked output
Authentication, redirects, cookies
- Pages behind a login: Convert HTML Pages with Authentication
- Custom headers and cookies are set on the converter as before; check the property names in the API reference
Packages, namespace, license key
Replace the Classic package with the Next package for your deployment target, change the using, and move the license key from the converter instance to the static Licensing class.
using EvoPdf; var converter = new HtmlToPdfConverter(); converter.LicenseKey = "…"; converter.ConversionDelay = 2; byte[] pdf = converter.ConvertUrl(url);
using EvoPdf.Next; Licensing.LicenseKey = "…"; // once per process var converter = new HtmlToPdfConverter(); converter.ConversionDelay = 2; byte[] pdf = converter.ConvertUrl(url);
EvoPdf.Next.HtmlToPdf.Windows, .Linux, .MacOS, or the .Arm64 variants. Windows and macOS need nothing else; on Linux a few system packages are required — see Getting Started on Linux. Classic runs on Windows only.The page sizing model is different
This is the change most likely to alter the look of your PDFs, because the two editions start from opposite defaults.
HtmlViewerWidth is the browser window width in pixels, and the HTML is laid out at that width. The PDF page is PdfPageSize — A4 by default — and, because FitWidth is true by default, the rendered content is scaled down to fit the fixed page width. With FitWidth = false, AutoSizePdfPage instead grows the page to show the content unscaled; ClipHtmlView forces the content to exactly the viewer width.
converter.HtmlViewerWidth = 1024; converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4; converter.PdfDocumentOptions.FitWidth = true; // default converter.PdfDocumentOptions.AutoSizePdfPage = true;
HtmlViewerWidth (default 1024 px) is again the viewport width — but by default the PDF page width is derived from it: AutoResizePdfPageWidth is true, so the page width becomes HtmlViewerWidth × 0.75 points (768 pt for 1024 px, plus any margins), while the page height still comes from PdfPageSize. Content wider than the viewer is scaled down to the page. To get an exact A4 page as in Classic, turn the auto width off.
converter.HtmlViewerWidth = 1024; converter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4; // default: page width = 1024 × 0.75 = 768 pt, height from A4 converter.PdfDocumentOptions.AutoResizePdfPageWidth = false; // exact A4 converter.PdfDocumentOptions.AutoResizePdfPageHeight = false;
Reflowing pages vs. fixed-width pages
If your HTML reflows with the viewport — fluid layouts, percentages, responsive CSS — HtmlViewerZoom works as in a browser: CSS pixels are scaled, so text and pixel-sized images grow or shrink with the zoom. If the page has a fixed overall width — a main container with an explicit width — Next may adjust the output to fit the PDF page width within a certain zoom range; outside that range the content is scaled proportionally, and above the upper limit anything beyond the right edge of the page is truncated. In Classic the same page would simply have been scaled down by FitWidth.
Practical rule
Set HtmlViewerWidth to the width your page is designed for, and decide once whether you want the page to follow the content (keep AutoResizePdfPageWidth = true) or the content to follow the page (false, plus a standard PdfPageSize). Start with the second when replacing Classic — it is the closest to what your users see today — and compare a few documents before switching the default. AutoResizePdfPageHeight = true is the Next equivalent of Classic's single-page output. Details: HTML to PDF Converter Options.
Headers and footers are described as HTML, not drawn as elements
In Classic a header is a container you add elements to — HtmlToPdfElement, TextElement, LineElement — with per-page visibility decided in the PrepareRenderPdfPageEvent handler. In Next a header is an HTML document with its own options object; page numbers are variables inside that HTML and per-page visibility is three booleans.
converter.PdfDocumentOptions.ShowHeader = true; converter.PdfHeaderOptions.HeaderHeight = 60; converter.PdfHeaderOptions.HeaderBackColor = Color.White; HtmlToPdfElement headerHtml = new HtmlToPdfElement(headerUrl); headerHtml.FitHeight = true; converter.PdfHeaderOptions.AddElement(headerHtml); // line under the header LineElement line = new LineElement(0, 59, headerWidth, 59); line.ForeColor = Color.Gray; converter.PdfHeaderOptions.AddElement(line); // page numbers: a TextElement with &p; and &P; placeholders converter.PdfFooterOptions.AddElement( new TextElement(0, 20, "Page &p; of &P;", font)); // hide on the first page, from an event handler converter.PrepareRenderPdfPageEvent += (p) => { if (p.PageNumber == 1) p.Page.ShowHeader = false; };
var header = converter.PdfDocumentOptions.PdfHtmlHeader; header.HtmlSourceUrl = headerUrl; // or header.Html + HtmlBaseUrl header.Height = 60; // or AutoSizeContentHeight = true header.FitHeight = true; header.AutoResizePdfMargins = true; // make room in the top margin // line under the header: CSS in the header HTML // page numbers: variables in the footer HTML converter.PdfDocumentOptions.PdfHtmlFooter.Html = "<div style=\"text-align:center\">Page {page_number} of {total_pages}</div>"; // per-page visibility: no event handler header.ShowInFirstPage = false; header.ShowInOddPages = true; header.ShowInEvenPages = true; header.ReserveSpaceAlways = true; // keep the space on hidden pages
TextElement, ImageElement or LineElement becomes markup in the header or footer HTML. Header and footer HTML is rendered by the same engine as the page, so web fonts, CSS and images work there too. Full sample: HTML Header and Footer with Page Numbers.Option map
| Classic | Next | Note |
|---|---|---|
using EvoPdf; | using EvoPdf.Next; | Namespace |
converter.LicenseKey | Licensing.LicenseKey | Static, set once |
PdfDocumentOptions.FitWidth = true (default) | PdfDocumentOptions.AutoResizePdfPageWidth = false | Content fits a fixed page width |
PdfDocumentOptions.AutoSizePdfPage | PdfDocumentOptions.AutoResizePdfPageWidth = true (default) | Page width follows the viewer width |
PdfDocumentOptions.SinglePage | PdfDocumentOptions.AutoResizePdfPageHeight = true (with AutoResizePdfPageWidth = true) | Whole content on one page |
PdfDocumentOptions.ShowHeader + PdfHeaderOptions | PdfDocumentOptions.PdfHtmlHeader | Same for footer |
PdfHeaderOptions.HeaderHeight | PdfHtmlHeader.Height / AutoSizeContentHeight | Min/Max content height available |
PdfHeaderOptions.AddElement(HtmlToPdfElement) | PdfHtmlHeader.Html or HtmlSourceUrl | One HTML document per header/footer |
TextElement with &p; / &P; | {page_number} / {total_pages} in the HTML | SkipVariablesParsing when not used |
PdfFooterOptions.PageNumberingStartIndex | PdfHtmlFooter.PageNumberOffset / TotalPagesOffset | Offsets for the page counters |
PrepareRenderPdfPageEvent → Page.ShowHeader | PdfHtmlHeader.ShowInFirstPage / ShowInOddPages / ShowInEvenPages | No event handler |
PdfDocumentOptions.TopSpacing / Y | PdfHtmlHeader.AutoResizePdfMargins | Header space added to the top margin |
ClipHtmlView, StretchToFit | — | No direct equivalent: the PDF page width follows HtmlViewerWidth (AutoResizePdfPageWidth, default true), so clipping or stretching the viewer content is not needed |
Beyond the API: what the new rendering engine changes in layout, fonts, JavaScript and image loading
Both engines render with the screen media type by default and both expose MediaType, so that part does not change. What changes is the engine underneath: Next renders exactly like a current Chrome, so pages look the way your browser shows them — and a few things Classic handled its own way now follow the browser.
Layout follows current web standards
- Flexbox, CSS grid, custom properties, modern selectors and ES2015+ JavaScript render as in Chrome — layouts that carried workarounds for the old engine can drop them, and pages that looked "acceptable" only because a rule was ignored may now look different
- Print CSS is honored:
@page,break-before/after/inside,page-break-*, so page breaks you controlled from the API can move into the stylesheet - Content is laid out at 96 DPI; the PDF page width follows
HtmlViewerWidthunless you fix it (see step 2)
Text and fonts
- Font fallback, hinting and metrics are Chrome's — line breaks, and therefore page breaks, can shift by a line compared with Classic output on the same document
- Web fonts (including WOFF2) are downloaded and embedded as subsets; PDFs with many fonts or large images can differ in size from Classic output
- Text stays selectable and searchable; with PDF/UA output it is also tagged
JavaScript and dynamic content
- Scripts run in a real browser engine: charts, frameworks and async data that the old engine could not execute now render — and pages that finish loading late need
ConversionDelayorTriggeringMode, as before JavaScriptEnabled,NavigationTimeoutandHtmlViewerWidthkeep their role
Resources and security defaults
- Lazy-loaded images are fetched by default (
LoadLazyImages); images that the old engine skipped will appear - Local files, insecure content and blocked hosts are governed by explicit options (
LocalFilesEnabledand the template-level equivalents) — check them if your HTML references file paths or mixed content - Sites served only over HTTP/2 or TLS 1.3 load directly — no need to download the HTML yourself and convert it as a string, as some Classic integrations did
Suggested order: run the Next demo application on your own pages first (online or the downloaded project), settle the page sizing options on two or three representative documents, then port the headers and footers. Most integrations need changes in exactly those two places and nowhere else.
Try your pages on the Next engine
The demo application runs without a license key, with a stamp on the output, so you can compare Classic and Next side by side before changing anything in production.