Weblitz Preview

Every option, rendered

For each option that changes what comes out: a small page, the C# that sets the option, and the pages Weblitz printed, beside the default where that shows the difference. Made on 2026-11-07 on macOS; the pages are drawn from the PDFs, which are downloads. What the engine noted is shown as it came back, including what it does not do yet.

Paper size and orientation

The page area changes with the paper: the dashed frame is the area's edge.

Reference: HtmlPdfOptions.Format, HtmlPdfOptions.Landscape, HtmlPdfOptions.Width, HtmlPdfOptions.Height

The page printed: article.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Field report: the Rhône sensors</title>
<style>
  body { font: 11pt/1.5 Arial, sans-serif; color: #1f2937; margin: 0; }
  .frame { border: 2px dashed #ff5a1f; padding: 6mm; }
  h1 { font-size: 22pt; margin: 0 0 3mm; color: #0b1020; }
  h2 { font-size: 14pt; margin: 6mm 0 2mm; color: #0b1020; }
  .band { background: linear-gradient(90deg, #0b1020, #3b0764); color: #fff; padding: 4mm 6mm; border-radius: 3mm; }
  .note { background: #fff7ed; border-left: 4px solid #ff5a1f; padding: 3mm 4mm; }
  table { border-collapse: collapse; width: 100%; margin-top: 3mm; }
  th, td { border: 1px solid #d1d5db; padding: 1.5mm 2.5mm; text-align: left; }
  th { background: #e0e7ff; }
  .page-break { break-before: page; }
</style></head>
<body>
<div class="frame">
  <div class="band"><h1 style="color:#fff">Field report: the Rhône sensors</h1>Page one of five: the dashed line is the page area's edge.</div>
  <h2>1. Where the sensors are</h2>
  <p>Forty-two stations along the river send a reading every ten minutes. The report below follows them from the lake to the sea, one section a page, so that the options that choose pages, sizes and margins show what they do.</p>
  <p class="note">A coloured band and a tinted note: printed with <code>PrintBackground</code> on, left white without it.</p>
  <table><tr><th>Station</th><th>Kilometre</th><th>Level (m)</th></tr>
    <tr><td>Genève</td><td>0</td><td>372.1</td></tr><tr><td>Seyssel</td><td>48</td><td>254.6</td></tr><tr><td>Lyon</td><td>232</td><td>162.3</td></tr></table>
</div>
<div class="frame page-break"><div class="band">Page two of five</div><h2>2. The upper river</h2><p>The upper river is fast and cold: its stations read the level every ten minutes and the temperature every hour.</p></div>
<div class="frame page-break"><div class="band">Page three of five</div><h2>3. Lyon</h2><p>At Lyon the Saône joins: the station reads both rivers.</p></div>
<div class="frame page-break"><div class="band">Page four of five</div><h2>4. The lower river</h2><p>Dams turn the lower river into a staircase of reaches.</p></div>
<div class="frame page-break"><div class="band">Page five of five</div><h2>5. The delta</h2><p>In the Camargue the river splits in two before the sea.</p></div>
</body></html>
Default: A4, portrait
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed
Pages
5
File
85,748 bytes (83.7 KB) · the PDF
Letter, landscape
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Format = "Letter", Landscape = true });
Page 1 of the PDF this code printed
Pages
5
File
91,185 bytes (89.0 KB) · the PDF
Width and height: 120 x 160 mm
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Width = "120mm", Height = "160mm" });
Page 1 of the PDF this code printed
Pages
6
File
79,991 bytes (78.1 KB) · the PDF

Margins

Without margins in the options or the page's @page rule, Chrome's default margins apply.

Reference: HtmlPdfOptions.Margin, HtmlMargins

The page printed: article.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Field report: the Rhône sensors</title>
<style>
  body { font: 11pt/1.5 Arial, sans-serif; color: #1f2937; margin: 0; }
  .frame { border: 2px dashed #ff5a1f; padding: 6mm; }
  h1 { font-size: 22pt; margin: 0 0 3mm; color: #0b1020; }
  h2 { font-size: 14pt; margin: 6mm 0 2mm; color: #0b1020; }
  .band { background: linear-gradient(90deg, #0b1020, #3b0764); color: #fff; padding: 4mm 6mm; border-radius: 3mm; }
  .note { background: #fff7ed; border-left: 4px solid #ff5a1f; padding: 3mm 4mm; }
  table { border-collapse: collapse; width: 100%; margin-top: 3mm; }
  th, td { border: 1px solid #d1d5db; padding: 1.5mm 2.5mm; text-align: left; }
  th { background: #e0e7ff; }
  .page-break { break-before: page; }
</style></head>
<body>
<div class="frame">
  <div class="band"><h1 style="color:#fff">Field report: the Rhône sensors</h1>Page one of five: the dashed line is the page area's edge.</div>
  <h2>1. Where the sensors are</h2>
  <p>Forty-two stations along the river send a reading every ten minutes. The report below follows them from the lake to the sea, one section a page, so that the options that choose pages, sizes and margins show what they do.</p>
  <p class="note">A coloured band and a tinted note: printed with <code>PrintBackground</code> on, left white without it.</p>
  <table><tr><th>Station</th><th>Kilometre</th><th>Level (m)</th></tr>
    <tr><td>Genève</td><td>0</td><td>372.1</td></tr><tr><td>Seyssel</td><td>48</td><td>254.6</td></tr><tr><td>Lyon</td><td>232</td><td>162.3</td></tr></table>
</div>
<div class="frame page-break"><div class="band">Page two of five</div><h2>2. The upper river</h2><p>The upper river is fast and cold: its stations read the level every ten minutes and the temperature every hour.</p></div>
<div class="frame page-break"><div class="band">Page three of five</div><h2>3. Lyon</h2><p>At Lyon the Saône joins: the station reads both rivers.</p></div>
<div class="frame page-break"><div class="band">Page four of five</div><h2>4. The lower river</h2><p>Dams turn the lower river into a staircase of reaches.</p></div>
<div class="frame page-break"><div class="band">Page five of five</div><h2>5. The delta</h2><p>In the Camargue the river splits in two before the sea.</p></div>
</body></html>
Default
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed
Pages
5
File
85,748 bytes (83.7 KB) · the PDF
25 mm all round
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Margin = HtmlMargins.All("25mm") });
Page 1 of the PDF this code printed
Pages
5
File
83,224 bytes (81.3 KB) · the PDF
Top, right, bottom, left
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Margin = new HtmlMargins("10mm", "45mm", "10mm", "10mm") });
Page 1 of the PDF this code printed
Pages
5
File
83,149 bytes (81.2 KB) · the PDF

Scale

The page is laid out as if the paper were larger or smaller, then printed on it: 0.1 to 2.

Reference: HtmlPdfOptions.Scale

The page printed: article.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Field report: the Rhône sensors</title>
<style>
  body { font: 11pt/1.5 Arial, sans-serif; color: #1f2937; margin: 0; }
  .frame { border: 2px dashed #ff5a1f; padding: 6mm; }
  h1 { font-size: 22pt; margin: 0 0 3mm; color: #0b1020; }
  h2 { font-size: 14pt; margin: 6mm 0 2mm; color: #0b1020; }
  .band { background: linear-gradient(90deg, #0b1020, #3b0764); color: #fff; padding: 4mm 6mm; border-radius: 3mm; }
  .note { background: #fff7ed; border-left: 4px solid #ff5a1f; padding: 3mm 4mm; }
  table { border-collapse: collapse; width: 100%; margin-top: 3mm; }
  th, td { border: 1px solid #d1d5db; padding: 1.5mm 2.5mm; text-align: left; }
  th { background: #e0e7ff; }
  .page-break { break-before: page; }
</style></head>
<body>
<div class="frame">
  <div class="band"><h1 style="color:#fff">Field report: the Rhône sensors</h1>Page one of five: the dashed line is the page area's edge.</div>
  <h2>1. Where the sensors are</h2>
  <p>Forty-two stations along the river send a reading every ten minutes. The report below follows them from the lake to the sea, one section a page, so that the options that choose pages, sizes and margins show what they do.</p>
  <p class="note">A coloured band and a tinted note: printed with <code>PrintBackground</code> on, left white without it.</p>
  <table><tr><th>Station</th><th>Kilometre</th><th>Level (m)</th></tr>
    <tr><td>Genève</td><td>0</td><td>372.1</td></tr><tr><td>Seyssel</td><td>48</td><td>254.6</td></tr><tr><td>Lyon</td><td>232</td><td>162.3</td></tr></table>
</div>
<div class="frame page-break"><div class="band">Page two of five</div><h2>2. The upper river</h2><p>The upper river is fast and cold: its stations read the level every ten minutes and the temperature every hour.</p></div>
<div class="frame page-break"><div class="band">Page three of five</div><h2>3. Lyon</h2><p>At Lyon the Saône joins: the station reads both rivers.</p></div>
<div class="frame page-break"><div class="band">Page four of five</div><h2>4. The lower river</h2><p>Dams turn the lower river into a staircase of reaches.</p></div>
<div class="frame page-break"><div class="band">Page five of five</div><h2>5. The delta</h2><p>In the Camargue the river splits in two before the sea.</p></div>
</body></html>
1 (default)
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed
Pages
5
File
85,748 bytes (83.7 KB) · the PDF
0.6
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Scale = 0.6 });
Page 1 of the PDF this code printed
Pages
5
File
96,673 bytes (94.4 KB) · the PDF
1.4
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Scale = 1.4 });
Page 1 of the PDF this code printed
Pages
5
File
82,536 bytes (80.6 KB) · the PDF

Choosing pages

The article has five pages; the PDF holds the ones asked for.

Reference: HtmlPdfOptions.PageRanges

The page printed: article.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Field report: the Rhône sensors</title>
<style>
  body { font: 11pt/1.5 Arial, sans-serif; color: #1f2937; margin: 0; }
  .frame { border: 2px dashed #ff5a1f; padding: 6mm; }
  h1 { font-size: 22pt; margin: 0 0 3mm; color: #0b1020; }
  h2 { font-size: 14pt; margin: 6mm 0 2mm; color: #0b1020; }
  .band { background: linear-gradient(90deg, #0b1020, #3b0764); color: #fff; padding: 4mm 6mm; border-radius: 3mm; }
  .note { background: #fff7ed; border-left: 4px solid #ff5a1f; padding: 3mm 4mm; }
  table { border-collapse: collapse; width: 100%; margin-top: 3mm; }
  th, td { border: 1px solid #d1d5db; padding: 1.5mm 2.5mm; text-align: left; }
  th { background: #e0e7ff; }
  .page-break { break-before: page; }
</style></head>
<body>
<div class="frame">
  <div class="band"><h1 style="color:#fff">Field report: the Rhône sensors</h1>Page one of five: the dashed line is the page area's edge.</div>
  <h2>1. Where the sensors are</h2>
  <p>Forty-two stations along the river send a reading every ten minutes. The report below follows them from the lake to the sea, one section a page, so that the options that choose pages, sizes and margins show what they do.</p>
  <p class="note">A coloured band and a tinted note: printed with <code>PrintBackground</code> on, left white without it.</p>
  <table><tr><th>Station</th><th>Kilometre</th><th>Level (m)</th></tr>
    <tr><td>Genève</td><td>0</td><td>372.1</td></tr><tr><td>Seyssel</td><td>48</td><td>254.6</td></tr><tr><td>Lyon</td><td>232</td><td>162.3</td></tr></table>
</div>
<div class="frame page-break"><div class="band">Page two of five</div><h2>2. The upper river</h2><p>The upper river is fast and cold: its stations read the level every ten minutes and the temperature every hour.</p></div>
<div class="frame page-break"><div class="band">Page three of five</div><h2>3. Lyon</h2><p>At Lyon the Saône joins: the station reads both rivers.</p></div>
<div class="frame page-break"><div class="band">Page four of five</div><h2>4. The lower river</h2><p>Dams turn the lower river into a staircase of reaches.</p></div>
<div class="frame page-break"><div class="band">Page five of five</div><h2>5. The delta</h2><p>In the Camargue the river splits in two before the sea.</p></div>
</body></html>
"2-3, 5"
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { PageRanges = "2-3, 5" });
Page 1 of the PDF this code printed Page 2 of the PDF this code printed Page 3 of the PDF this code printed
Pages
3
File
54,639 bytes (53.4 KB) · the PDF

The page's own @page size

A page that asks for its paper size gets it by default; with PreferCssPageSize false, the options' Format wins.

Reference: HtmlPdfOptions.PreferCssPageSize

The page printed: css-page-size.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>A card of its own size</title>
<style>
  @page { size: A5 landscape; margin: 10mm; }
  body { font: 12pt/1.4 Arial, sans-serif; margin: 0; }
  .card { border: 2px solid #0b1020; border-radius: 4mm; padding: 6mm; background: #f0fdfa; }
  h1 { margin: 0 0 2mm; font-size: 18pt; }
</style></head>
<body><div class="card"><h1>Admission: Hall 4</h1>This page asks for <code>@page { size: A5 landscape }</code>.</div></body></html>
true (default): A5 landscape, as the page asks
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed
Pages
1
File
39,665 bytes (38.7 KB) · the PDF
false: the options' A4
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { PreferCssPageSize = false, Format = "A4" });
Page 1 of the PDF this code printed
Pages
1
File
39,680 bytes (38.8 KB) · the PDF

Scripts and the virtual clock

Scripts run once before printing; timers run in virtual time for WaitFor (5 seconds by default), so a page's 2-second timer fires and its 8-second one only with a longer wait. beforeprint runs just before the PDF is made.

Reference: HtmlPdfOptions.Scripts, HtmlScripts

The page printed: scripts.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Scripts</title>
<style>body { font: 13pt/1.5 Arial, sans-serif; margin: 0; } li { margin: 2mm 0; } .js { color: #047857; font-weight: bold; }</style></head>
<body>
<h1>What the page's scripts did</h1>
<ul id="log"><li>Written in the HTML.</li></ul>
<script>
  const log = (text) => { const li = document.createElement('li'); li.className = 'js'; li.textContent = text; document.getElementById('log').append(li); };
  log('Added by the script as the page loaded.');
  setTimeout(() => log('Added by a timer after 2 seconds (virtual time).'), 2000);
  setTimeout(() => log('Added by a timer after 8 seconds (virtual time).'), 8000);
  addEventListener('beforeprint', () => log('Added on beforeprint, just before printing.'));
</script>
</body></html>
Default: scripts on, 5 s of virtual time
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed
Pages
1
File
36,218 bytes (35.4 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (2033 ms of virtual time, 7 tasks; 0 canvases drawn).
WaitFor 10 s
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Scripts = HtmlScripts.Default with { WaitFor = TimeSpan.FromSeconds(10) } });
Page 1 of the PDF this code printed
Pages
1
File
37,010 bytes (36.1 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (8033 ms of virtual time, 10 tasks; 0 canvases drawn).
Scripts off
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Scripts = HtmlScripts.Off });
Page 1 of the PDF this code printed
Pages
1
File
30,676 bytes (30.0 KB) · the PDF

The network

The network is off by default: a page's web addresses are not fetched and noted instead. Allow the hosts a page may load from (assets is a server the generator starts on this machine).

Reference: HtmlPdfOptions.Network, HtmlNetwork, HtmlPdfOptions.BaseUrl

The page printed: network.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Network</title>
<link rel="stylesheet" href="brand.css">
<style>body { font: 12pt/1.5 Arial, sans-serif; margin: 0; } img { width: 40mm; display: block; margin: 4mm 0; }</style></head>
<body>
<h1 class="brand">A page whose picture and CSS are on a server</h1>
<img src="logo.svg" alt="The logo, fetched from the server">
<p>The heading's colour comes from <code>brand.css</code> and the picture from <code>logo.svg</code>, both fetched over HTTP.</p>
</body></html>
Off (default)
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { BaseUrl = assets });
Page 1 of the PDF this code printed
Pages
1
File
44,119 bytes (43.1 KB) · the PDF
Notes
  • Info resourceRefused: StyleSheet http://127.0.0.1:18431/brand.css: no resource loader was given (only data: URLs load).
  • Info resourceRefused: Image http://127.0.0.1:18431/logo.svg: no resource loader was given (only data: URLs load).
  • Info notImplemented: A picture that did not load shows its alternative text; Chrome's broken-image icon beside it is laid out but not drawn.
Allow the assets' host
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { BaseUrl = assets, Network = HtmlNetwork.Allow(assets.Host) });
Page 1 of the PDF this code printed
Pages
1
File
45,952 bytes (44.9 KB) · the PDF

Pages behind a login

A page your server shows only to signed-in users prints with what a browser would send: a bearer token, a session cookie, or a password for HTTP authentication. Each goes only to the hosts it names, by default the document's own (assets is a server the generator starts on this machine; its account pages need one of them).

Reference: HtmlNetwork.Headers, HtmlNetwork.Cookies, HtmlNetwork.AcceptCookies, HtmlNetwork.Credentials, HtmlCookie

The page printed: assets/account/statement.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Account statement</title>
<link rel="stylesheet" href="../brand.css">
<style>
  body { font: 11pt/1.5 Arial, sans-serif; margin: 0; }
  table { border-collapse: collapse; width: 100%; margin-top: 6mm; }
  th, td { border-bottom: 1px solid #d0d4dc; padding: 2mm 3mm; text-align: left; }
  td.n { text-align: right; font-variant-numeric: tabular-nums; }
  .who { color: #555; }
</style></head>
<body>
<h1 class="brand">Account statement, October 2026</h1>
<p class="who">Signed in as <strong id="user">a customer</strong>: this page is served only with a valid session.</p>
<table>
  <tr><th>Date</th><th>Description</th><th class="n">Amount</th></tr>
  <tr><td>2026-10-03</td><td>Subscription, October</td><td class="n">-49.00</td></tr>
  <tr><td>2026-10-14</td><td>Refund, order 1182</td><td class="n">12.50</td></tr>
  <tr><td>2026-10-28</td><td>Top-up</td><td class="n">200.00</td></tr>
</table>
<script>
  // what the page's own scripts see of the session (an HttpOnly cookie never shows here)
  const theme = document.cookie.split('; ').find(c => c.startsWith('theme='));
  if (theme) document.getElementById('user').textContent += ' (theme ' + theme.slice(6) + ')';
</script>
</body></html>
A bearer token
var result = HtmlToPdf.RenderUrl(new Uri(assets, "account/statement.html"), new HtmlPdfOptions
{
    Network = HtmlNetwork.Allow(assets.Host).WithBearerToken(accessToken),
});
Page 1 of the PDF this code printed
Pages
1
File
43,239 bytes (42.2 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (17 ms of virtual time, 2 tasks; 0 canvases drawn).
A session cookie
var result = HtmlToPdf.RenderUrl(new Uri(assets, "account/statement.html"), new HtmlPdfOptions
{
    Network = HtmlNetwork.Allow(assets.Host)
        .WithCookie(new HtmlCookie("session", sessionId) { HttpOnly = true })
        .WithCookie(new HtmlCookie("theme", "dark")),
});
Page 1 of the PDF this code printed
Pages
1
File
44,446 bytes (43.4 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (17 ms of virtual time, 2 tasks; 0 canvases drawn).

PDF compression

The same pages, deflated more or less: the files' sizes below, measured when these pages were made.

Reference: HtmlPdfOptions.Compression, HtmlPdfCompression

The page printed: article.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Field report: the Rhône sensors</title>
<style>
  body { font: 11pt/1.5 Arial, sans-serif; color: #1f2937; margin: 0; }
  .frame { border: 2px dashed #ff5a1f; padding: 6mm; }
  h1 { font-size: 22pt; margin: 0 0 3mm; color: #0b1020; }
  h2 { font-size: 14pt; margin: 6mm 0 2mm; color: #0b1020; }
  .band { background: linear-gradient(90deg, #0b1020, #3b0764); color: #fff; padding: 4mm 6mm; border-radius: 3mm; }
  .note { background: #fff7ed; border-left: 4px solid #ff5a1f; padding: 3mm 4mm; }
  table { border-collapse: collapse; width: 100%; margin-top: 3mm; }
  th, td { border: 1px solid #d1d5db; padding: 1.5mm 2.5mm; text-align: left; }
  th { background: #e0e7ff; }
  .page-break { break-before: page; }
</style></head>
<body>
<div class="frame">
  <div class="band"><h1 style="color:#fff">Field report: the Rhône sensors</h1>Page one of five: the dashed line is the page area's edge.</div>
  <h2>1. Where the sensors are</h2>
  <p>Forty-two stations along the river send a reading every ten minutes. The report below follows them from the lake to the sea, one section a page, so that the options that choose pages, sizes and margins show what they do.</p>
  <p class="note">A coloured band and a tinted note: printed with <code>PrintBackground</code> on, left white without it.</p>
  <table><tr><th>Station</th><th>Kilometre</th><th>Level (m)</th></tr>
    <tr><td>Genève</td><td>0</td><td>372.1</td></tr><tr><td>Seyssel</td><td>48</td><td>254.6</td></tr><tr><td>Lyon</td><td>232</td><td>162.3</td></tr></table>
</div>
<div class="frame page-break"><div class="band">Page two of five</div><h2>2. The upper river</h2><p>The upper river is fast and cold: its stations read the level every ten minutes and the temperature every hour.</p></div>
<div class="frame page-break"><div class="band">Page three of five</div><h2>3. Lyon</h2><p>At Lyon the Saône joins: the station reads both rivers.</p></div>
<div class="frame page-break"><div class="band">Page four of five</div><h2>4. The lower river</h2><p>Dams turn the lower river into a staircase of reaches.</p></div>
<div class="frame page-break"><div class="band">Page five of five</div><h2>5. The delta</h2><p>In the Camargue the river splits in two before the sea.</p></div>
</body></html>
None
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Compression = HtmlPdfCompression.None });
Pages
5
File
157,529 bytes (153.8 KB) · the PDF
Fastest (default)
var result = HtmlToPdf.Render(html);
Pages
5
File
85,748 bytes (83.7 KB) · the PDF
Default
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Compression = HtmlPdfCompression.Default });
Pages
5
File
68,898 bytes (67.3 KB) · the PDF
Smallest
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Compression = HtmlPdfCompression.Smallest });
Pages
5
File
67,853 bytes (66.3 KB) · the PDF

Passwords and permissions

The PDF is encrypted (AES-256): a reader asks for the user password, and without the owner's it may not copy (here).

Reference: HtmlPdfOptions.Security, HtmlPdfSecurity

The page printed: article.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Field report: the Rhône sensors</title>
<style>
  body { font: 11pt/1.5 Arial, sans-serif; color: #1f2937; margin: 0; }
  .frame { border: 2px dashed #ff5a1f; padding: 6mm; }
  h1 { font-size: 22pt; margin: 0 0 3mm; color: #0b1020; }
  h2 { font-size: 14pt; margin: 6mm 0 2mm; color: #0b1020; }
  .band { background: linear-gradient(90deg, #0b1020, #3b0764); color: #fff; padding: 4mm 6mm; border-radius: 3mm; }
  .note { background: #fff7ed; border-left: 4px solid #ff5a1f; padding: 3mm 4mm; }
  table { border-collapse: collapse; width: 100%; margin-top: 3mm; }
  th, td { border: 1px solid #d1d5db; padding: 1.5mm 2.5mm; text-align: left; }
  th { background: #e0e7ff; }
  .page-break { break-before: page; }
</style></head>
<body>
<div class="frame">
  <div class="band"><h1 style="color:#fff">Field report: the Rhône sensors</h1>Page one of five: the dashed line is the page area's edge.</div>
  <h2>1. Where the sensors are</h2>
  <p>Forty-two stations along the river send a reading every ten minutes. The report below follows them from the lake to the sea, one section a page, so that the options that choose pages, sizes and margins show what they do.</p>
  <p class="note">A coloured band and a tinted note: printed with <code>PrintBackground</code> on, left white without it.</p>
  <table><tr><th>Station</th><th>Kilometre</th><th>Level (m)</th></tr>
    <tr><td>Genève</td><td>0</td><td>372.1</td></tr><tr><td>Seyssel</td><td>48</td><td>254.6</td></tr><tr><td>Lyon</td><td>232</td><td>162.3</td></tr></table>
</div>
<div class="frame page-break"><div class="band">Page two of five</div><h2>2. The upper river</h2><p>The upper river is fast and cold: its stations read the level every ten minutes and the temperature every hour.</p></div>
<div class="frame page-break"><div class="band">Page three of five</div><h2>3. Lyon</h2><p>At Lyon the Saône joins: the station reads both rivers.</p></div>
<div class="frame page-break"><div class="band">Page four of five</div><h2>4. The lower river</h2><p>Dams turn the lower river into a staircase of reaches.</p></div>
<div class="frame page-break"><div class="band">Page five of five</div><h2>5. The delta</h2><p>In the Camargue the river splits in two before the sea.</p></div>
</body></html>
A user password, no copying
var result = HtmlToPdf.Render(html, new HtmlPdfOptions
{
    Security = new HtmlPdfSecurity { UserPassword = "open-me", OwnerPassword = "owner-secret", PermitCopying = false },
});
Pages
5
File
88,762 bytes (86.7 KB), encrypted · the PDF

Title, author and PDF/A

What the PDF says of itself; PDF/A-2b for archives.

Reference: HtmlPdfOptions.Title, HtmlPdfOptions.Author, HtmlPdfOptions.PdfA

The page printed: article.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Field report: the Rhône sensors</title>
<style>
  body { font: 11pt/1.5 Arial, sans-serif; color: #1f2937; margin: 0; }
  .frame { border: 2px dashed #ff5a1f; padding: 6mm; }
  h1 { font-size: 22pt; margin: 0 0 3mm; color: #0b1020; }
  h2 { font-size: 14pt; margin: 6mm 0 2mm; color: #0b1020; }
  .band { background: linear-gradient(90deg, #0b1020, #3b0764); color: #fff; padding: 4mm 6mm; border-radius: 3mm; }
  .note { background: #fff7ed; border-left: 4px solid #ff5a1f; padding: 3mm 4mm; }
  table { border-collapse: collapse; width: 100%; margin-top: 3mm; }
  th, td { border: 1px solid #d1d5db; padding: 1.5mm 2.5mm; text-align: left; }
  th { background: #e0e7ff; }
  .page-break { break-before: page; }
</style></head>
<body>
<div class="frame">
  <div class="band"><h1 style="color:#fff">Field report: the Rhône sensors</h1>Page one of five: the dashed line is the page area's edge.</div>
  <h2>1. Where the sensors are</h2>
  <p>Forty-two stations along the river send a reading every ten minutes. The report below follows them from the lake to the sea, one section a page, so that the options that choose pages, sizes and margins show what they do.</p>
  <p class="note">A coloured band and a tinted note: printed with <code>PrintBackground</code> on, left white without it.</p>
  <table><tr><th>Station</th><th>Kilometre</th><th>Level (m)</th></tr>
    <tr><td>Genève</td><td>0</td><td>372.1</td></tr><tr><td>Seyssel</td><td>48</td><td>254.6</td></tr><tr><td>Lyon</td><td>232</td><td>162.3</td></tr></table>
</div>
<div class="frame page-break"><div class="band">Page two of five</div><h2>2. The upper river</h2><p>The upper river is fast and cold: its stations read the level every ten minutes and the temperature every hour.</p></div>
<div class="frame page-break"><div class="band">Page three of five</div><h2>3. Lyon</h2><p>At Lyon the Saône joins: the station reads both rivers.</p></div>
<div class="frame page-break"><div class="band">Page four of five</div><h2>4. The lower river</h2><p>Dams turn the lower river into a staircase of reaches.</p></div>
<div class="frame page-break"><div class="band">Page five of five</div><h2>5. The delta</h2><p>In the Camargue the river splits in two before the sea.</p></div>
</body></html>
Title, author, PDF/A
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Title = "Rhône field report", Author = "Hydrology team", PdfA = true });
Pages
5
File
90,049 bytes (87.9 KB), PDF/A · the PDF

Limits

A page held to its limits: here two pages at most. The render stops there, prints what it has, and says so: Completed is false and a note tells which limit.

Reference: HtmlPdfOptions.Limits, HtmlPdfLimits, HtmlPdfResult.Completed

The page printed: article.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Field report: the Rhône sensors</title>
<style>
  body { font: 11pt/1.5 Arial, sans-serif; color: #1f2937; margin: 0; }
  .frame { border: 2px dashed #ff5a1f; padding: 6mm; }
  h1 { font-size: 22pt; margin: 0 0 3mm; color: #0b1020; }
  h2 { font-size: 14pt; margin: 6mm 0 2mm; color: #0b1020; }
  .band { background: linear-gradient(90deg, #0b1020, #3b0764); color: #fff; padding: 4mm 6mm; border-radius: 3mm; }
  .note { background: #fff7ed; border-left: 4px solid #ff5a1f; padding: 3mm 4mm; }
  table { border-collapse: collapse; width: 100%; margin-top: 3mm; }
  th, td { border: 1px solid #d1d5db; padding: 1.5mm 2.5mm; text-align: left; }
  th { background: #e0e7ff; }
  .page-break { break-before: page; }
</style></head>
<body>
<div class="frame">
  <div class="band"><h1 style="color:#fff">Field report: the Rhône sensors</h1>Page one of five: the dashed line is the page area's edge.</div>
  <h2>1. Where the sensors are</h2>
  <p>Forty-two stations along the river send a reading every ten minutes. The report below follows them from the lake to the sea, one section a page, so that the options that choose pages, sizes and margins show what they do.</p>
  <p class="note">A coloured band and a tinted note: printed with <code>PrintBackground</code> on, left white without it.</p>
  <table><tr><th>Station</th><th>Kilometre</th><th>Level (m)</th></tr>
    <tr><td>Genève</td><td>0</td><td>372.1</td></tr><tr><td>Seyssel</td><td>48</td><td>254.6</td></tr><tr><td>Lyon</td><td>232</td><td>162.3</td></tr></table>
</div>
<div class="frame page-break"><div class="band">Page two of five</div><h2>2. The upper river</h2><p>The upper river is fast and cold: its stations read the level every ten minutes and the temperature every hour.</p></div>
<div class="frame page-break"><div class="band">Page three of five</div><h2>3. Lyon</h2><p>At Lyon the Saône joins: the station reads both rivers.</p></div>
<div class="frame page-break"><div class="band">Page four of five</div><h2>4. The lower river</h2><p>Dams turn the lower river into a staircase of reaches.</p></div>
<div class="frame page-break"><div class="band">Page five of five</div><h2>5. The delta</h2><p>In the Camargue the river splits in two before the sea.</p></div>
</body></html>
MaxPages = 2
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Limits = HtmlPdfLimits.Default with { MaxPages = 2 } });
Console.WriteLine($"{result.PageCount} pages, completed: {result.Completed}");
Page 1 of the PDF this code printed Page 2 of the PDF this code printed
Pages
2, stopped early (Completed false)
File
67,058 bytes (65.5 KB) · the PDF
Notes
  • Warning limitReached: the document was cut after 2 pages.

Notes: what could not be done

A page's own problems never throw: a picture missing, a host not allowed, a font the machine lacks, a script that throws. Each is a note.

Reference: HtmlPdfResult.Notes, HtmlPdfNote, HtmlPdfNoteSeverity

The page printed: notes.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Notes</title>
<style>body { font: 12pt/1.5 Arial, sans-serif; margin: 0; } .odd { font-family: "Some Font Nobody Has", serif; }</style></head>
<body>
<h1>A page with problems</h1>
<p><img src="missing-picture.png" alt="A picture that is not there" width="120" height="60"></p>
<p class="odd">Text in a font family the machine does not have.</p>
<p><img src="https://cdn.example.com/banner.png" alt="A picture on another host" width="120" height="60"></p>
<script>
  document.body.append('The script ran up to here; ');
  undefinedFunction();
</script>
</body></html>
A page with problems
var result = HtmlToPdf.Render(html);
foreach (var note in result.Notes)
    Console.WriteLine($"{note.Severity} {note.Code}: {note.Message}");
Page 1 of the PDF this code printed
Pages
1
File
56,265 bytes (54.9 KB) · the PDF
Notes
  • Warning scriptError: ReferenceError: undefinedFunction is not defined | at about:blank#script-25:11:3 | at HostDelegate.<anonymous> (<anonymous>) | at Object.hostCall (ssrs2-dom.js:35362:11)
  • Warning resourceFailed: Image "missing-picture.png" is not a URL that resolves against no base URL.
  • Info resourceRefused: Image https://cdn.example.com/banner.png: no resource loader was given (only data: URLs load).
  • Info scriptsRan: The page's scripts ran (17 ms of virtual time, 4 tasks; 0 canvases drawn).
  • Info notImplemented: A picture that did not load shows its alternative text; Chrome's broken-image icon beside it is laid out but not drawn.
  • Info fontFamilyMissing: The font family "Some Font Nobody Has" is not on this machine: its text goes to the next family.

The browser the page sees

By default a page sees desktop Chrome 156 on the machine's own OS. These pages were made on macOS.

Reference: HtmlPdfOptions.UserAgent, HtmlPdfOptions.UserAgentMetadata, HtmlUserAgentMetadata, HtmlUserAgentBrand

The page printed: user-agent.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Who am I?</title>
<style>body { font: 11pt/1.5 Arial, sans-serif; margin: 0; } dt { font-weight: bold; margin-top: 3mm; } dd { margin: 0; font-family: "Courier New", monospace; font-size: 10pt; }</style></head>
<body>
<h1>What the page sees</h1>
<dl id="out"></dl>
<script>
  const out = document.getElementById('out');
  const show = (name, value) => { const dt = document.createElement('dt'); dt.textContent = name; const dd = document.createElement('dd'); dd.textContent = value; out.append(dt, dd); };
  show('navigator.userAgent', navigator.userAgent);
  show('navigator.platform', navigator.platform);
  const data = navigator.userAgentData;
  show('navigator.userAgentData.brands', data ? data.brands.map(b => b.brand + ' ' + b.version).join(', ') : '(none)');
  show('navigator.userAgentData.platform', data ? data.platform : '(none)');
</script>
</body></html>
Default
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed
Pages
1
File
44,873 bytes (43.8 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (17 ms of virtual time, 2 tasks; 0 canvases drawn).
A User-Agent and its metadata
var result = HtmlToPdf.Render(html, new HtmlPdfOptions
{
    UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.0.0 Safari/537.36 InvoiceBot/2.1",
    UserAgentMetadata = HtmlUserAgentMetadata.ChromeOnThisMachine with
    {
        Platform = "Windows",
        Brands = [new("InvoiceBot", "2"), new("Chromium", "156")],
    },
});
Page 1 of the PDF this code printed
Pages
1
File
45,030 bytes (44.0 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (17 ms of virtual time, 2 tasks; 0 canvases drawn).

Locale, time zone and clock

What the page's scripts see of the world: the same values every run, so the same input gives the same PDF.

Reference: HtmlPdfOptions.Locale, HtmlPdfOptions.TimeZone, HtmlPdfOptions.Now

The page printed: locale.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Locale, time zone and clock</title>
<style>body { font: 12pt/1.5 Arial, sans-serif; margin: 0; } dt { font-weight: bold; margin-top: 3mm; } dd { margin: 0; }</style></head>
<body>
<h1>Dates and numbers, as the page's scripts write them</h1>
<dl id="out"></dl>
<script>
  const out = document.getElementById('out');
  const show = (name, value) => { const dt = document.createElement('dt'); dt.textContent = name; const dd = document.createElement('dd'); dd.textContent = value; out.append(dt, dd); };
  const now = new Date();
  show('new Date().toString()', now.toString());
  show('toLocaleDateString(undefined, { dateStyle: "full" })', now.toLocaleDateString(undefined, { dateStyle: 'full' }));
  show('Intl.NumberFormat(undefined, { style: "currency", currency: "EUR" })', new Intl.NumberFormat(undefined, { style: 'currency', currency: 'EUR' }).format(1234567.891));
  show('Intl.DateTimeFormat().resolvedOptions().timeZone', Intl.DateTimeFormat().resolvedOptions().timeZone);
</script>
</body></html>
Default
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed
Pages
1
File
48,120 bytes (47.0 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (17 ms of virtual time, 2 tasks; 0 canvases drawn).
de-CH, Europe/Zurich, a fixed clock
var result = HtmlToPdf.Render(html, new HtmlPdfOptions
{
    Locale = "de-CH",
    TimeZone = "Europe/Zurich",
    Now = new DateTimeOffset(2026, 11, 7, 9, 30, 0, TimeSpan.FromHours(1)),
});
Page 1 of the PDF this code printed
Pages
1
File
50,717 bytes (49.5 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (17 ms of virtual time, 2 tasks; 0 canvases drawn).

Installed fonts

By default the machine's fonts are used after the page's own @font-face fonts; off, only the bundled faces. These pages were made on macOS.

Reference: HtmlPdfOptions.UseInstalledFonts

The page printed: fonts.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Fonts</title>
<style>body { font: 13pt/1.6 Arial, sans-serif; margin: 0; } p { margin: 2mm 0; } span { color: #6b7280; font: 9pt Arial; }</style></head>
<body>
<h1>Families, by name</h1>
<p style="font-family: Arial">Arial: The quick brown fox jumps. <span>(bundled metric-compatible face)</span></p>
<p style="font-family: 'Times New Roman'">Times New Roman: The quick brown fox jumps. <span>(bundled)</span></p>
<p style="font-family: 'Segoe UI'">Segoe UI: The quick brown fox jumps. <span>(bundled)</span></p>
<p style="font-family: 'Helvetica Neue', serif">Helvetica Neue: The quick brown fox jumps. <span>(installed on macOS; else the serif fallback)</span></p>
<p style="font-family: Avenir, serif">Avenir: The quick brown fox jumps. <span>(installed on macOS; else the serif fallback)</span></p>
<p style="font-family: 'Hiragino Sans', serif">日本語のテキスト <span>(Japanese: the machine's fonts)</span></p>
</body></html>
true (default)
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed
Pages
1
File
105,574 bytes (103.1 KB) · the PDF
Notes
  • Info fontFamilyMissing: The font family "Segoe UI" is not on this machine: its text goes to the next family.
false: the bundled faces only
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { UseInstalledFonts = false });
Page 1 of the PDF this code printed
Pages
1
File
36,473 bytes (35.6 KB) · the PDF
Notes
  • Info fontFamilyMissing: The font family "Helvetica Neue" is not in the font profile "reference": its text goes to the next family.
  • Info fontFamilyMissing: The font family "Avenir" is not in the font profile "reference": its text goes to the next family.
  • Info fontFamilyMissing: The font family "Hiragino Sans" is not in the font profile "reference": its text goes to the next family.
  • Warning missingGlyph: No font of 'Hiragino Sans, serif' nor the fallback has a glyph for a character: drawn as .notdef.

Lists that load as you scroll

An infinite list loads its next ten orders each time its bottom comes into view. Without a scroll option, Weblitz's IntersectionObserver reports the bottom visible once, so the PDF holds twenty; ScrollThrough scrolls the window down a window height at a time, each step waiting ScrollStepWait of virtual time, so the list loads to its end and all sixty are printed.

Reference: HtmlPdfOptions.ScrollThrough, HtmlPdfOptions.ScrollStepWait

The page printed: lazy-list.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>A list that loads as you scroll</title>
<style>
  body { font: 11pt/1.4 Arial, sans-serif; margin: 0; }
  li { padding: 2.2mm 3mm; min-height: 24mm; box-sizing: border-box; border-bottom: 1px solid #e5e7eb; }
  li:nth-child(odd) { background: #f8fafc; }
  #more { padding: 3mm; color: #6b7280; font-style: italic; }
</style></head>
<body>
<h1>Orders, loaded 10 at a time as you scroll</h1>
<ol id="list"></ol>
<p id="more">Scroll for more…</p>
<script>
  // An infinite list as sites write it: the next ten orders load when the bottom comes into view, up to 60
  let loaded = 0;
  const list = document.getElementById('list');
  function loadMore() {
    for (let i = 0; i < 10 && loaded < 60; i++) {
      loaded++;
      const li = document.createElement('li');
      li.textContent = `Order #${1000 + loaded}: ${['Frankfurt', 'Lyon', 'Milano', 'Basel', 'Gent'][loaded % 5]}, ${(loaded * 37) % 900 + 100} EUR`;
      list.append(li);
    }
    if (loaded >= 60) document.getElementById('more').textContent = 'All 60 orders loaded.';
  }
  loadMore();
  new IntersectionObserver((entries) => { if (entries.some(e => e.isIntersecting)) setTimeout(loadMore, 100); })
    .observe(document.getElementById('more'));
</script>
</body></html>
Default: not scrolled
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed Page 2 of the PDF this code printed
Pages
2
File
53,525 bytes (52.3 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (133 ms of virtual time, 5 tasks; 0 canvases drawn).
ScrollThrough
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { ScrollThrough = true });
Page 1 of the PDF this code printed Page 2 of the PDF this code printed
Pages
6
File
58,672 bytes (57.3 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (884 ms of virtual time, 40 tasks; 0 canvases drawn).

Scrolling to a section first

ScrollTo scrolls the window before printing, as a user would before pressing Print: the page's scroll events and IntersectionObserver callbacks see it (here the sections that went off screen, and scrollY). A scroll timeline on the page's own scroll prints at its start either way, as Chrome prints it. The PDF still holds the whole document from its top.

Reference: HtmlPdfOptions.ScrollTo

The page printed: scroll-effects.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Effects that wait for the scroll</title>
<style>
  body { font: 11pt/1.5 Arial, sans-serif; margin: 0; }
  .progress { height: 5mm; background: #e5e7eb; border-radius: 3mm; overflow: hidden; margin: 2mm 0 5mm; }
  .progress i { display: block; height: 100%; width: 100%; transform-origin: left; background: linear-gradient(90deg, #22d3ee, #a855f7);
                animation: fill linear both; animation-timeline: scroll(root); }
  @keyframes fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
  section { min-height: 230mm; padding: 6mm; border-left: 4px solid #e5e7eb; margin-bottom: 4mm; }
  section.on { border-left-color: #ff5a1f; background: #fff7ed; }
  .state { font: bold 10pt "Courier New", monospace; color: #6b7280; }
  section.on .state { color: #c2410c; }
  #scrolled { font: 10pt "Courier New", monospace; }
</style></head>
<body>
<h1>Sections that change when they are seen</h1>
<p id="scrolled">window.scrollY when printed: 0</p>
<p>Reading progress (a scroll-driven animation on the page's scroll: printed at its start, scrolled or not, as Chrome prints it):</p>
<div class="progress"><i></i></div>
<section id="intro"><h2>1. Introduction</h2><p class="state">not seen yet</p></section>
<section id="method"><h2>2. Method</h2><p class="state">not seen yet</p></section>
<section id="results"><h2>3. Results</h2><p class="state">not seen yet</p></section>
<script>
  // Each section says whether it is on screen (IntersectionObserver); the bar above follows the page's scroll
  const observer = new IntersectionObserver((entries) => {
    for (const e of entries) {
      e.target.classList.toggle('on', e.isIntersecting);
      e.target.querySelector('.state').textContent = e.isIntersecting ? 'on screen' : 'off screen';
    }
  });
  document.querySelectorAll('section').forEach(s => observer.observe(s));
  addEventListener('scroll', () => { document.getElementById('scrolled').textContent = 'window.scrollY when printed: ' + Math.round(scrollY); });
</script>
</body></html>
Default: not scrolled
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed Page 2 of the PDF this code printed Page 3 of the PDF this code printed
Pages
3
File
69,330 bytes (67.7 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (17 ms of virtual time, 4 tasks; 0 canvases drawn).
ScrollTo "#results"
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { ScrollTo = "#results" });
Page 1 of the PDF this code printed Page 2 of the PDF this code printed Page 3 of the PDF this code printed
Pages
3
File
70,552 bytes (68.9 KB) · the PDF
Notes
  • Info scriptsRan: The page's scripts ran (50 ms of virtual time, 6 tasks; 0 canvases drawn).

Printing a part of the page

Region prints a part of the document, from a start (the scroll position, a length, an element) for a height; what lies above and below is left out, and the part is laid out on pages as a whole document is.

Reference: HtmlPdfOptions.Region, HtmlPrintRegion

The page printed: chapters.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Five chapters</title>
<style>
  body { font: 11pt/1.6 Arial, sans-serif; margin: 0; }
  .chapter { padding: 6mm; margin-bottom: 6mm; border: 2px solid #0b1020; border-radius: 3mm; }
  .chapter h2 { margin-top: 0; }
  .chapter:nth-child(odd) { background: #f0fdfa; }
  .ruler { height: 100mm; background: repeating-linear-gradient(#fff 0 9.5mm, #cbd5e1 9.5mm 10mm); border: 1px solid #cbd5e1; }
</style></head>
<body>
<div class="chapter" id="chapter-1"><h2>Chapter 1</h2><div class="ruler"></div></div>
<div class="chapter" id="chapter-2"><h2>Chapter 2</h2><div class="ruler"></div></div>
<div class="chapter" id="chapter-3"><h2>Chapter 3: printed from here</h2><p>The region starts at this chapter's top and runs 1200 CSS pixels down.</p><div class="ruler"></div></div>
<div class="chapter" id="chapter-4"><h2>Chapter 4</h2><div class="ruler"></div></div>
<div class="chapter" id="chapter-5"><h2>Chapter 5</h2><div class="ruler"></div></div>
</body></html>
Default: the whole document
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed Page 2 of the PDF this code printed Page 3 of the PDF this code printed
Pages
3
File
46,933 bytes (45.8 KB) · the PDF
1200 px from #chapter-3
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { Region = HtmlPrintRegion.Of("#chapter-3", "1200px") });
Page 1 of the PDF this code printed Page 2 of the PDF this code printed
Pages
2
File
45,114 bytes (44.1 KB) · the PDF

Chrome's experimental features

Off by default, as stable Chrome prints; on, the features Chrome 156 has behind its "Experimental Web Platform features" flag that Weblitz has built, grid lanes among them.

Reference: HtmlPdfOptions.ExperimentalWebFeatures

The page printed: grid-lanes.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Grid lanes</title>
<style>
  body { font: 11pt/1.4 Arial, sans-serif; margin: 0; }
  .wall { display: grid-lanes; grid-template-columns: repeat(3, 1fr); gap: 4mm; }
  .card { border-radius: 3mm; padding: 4mm; color: #fff; }
  .card:nth-child(4n+1) { background: #0b1020; } .card:nth-child(4n+2) { background: #7c3aed; }
  .card:nth-child(4n+3) { background: #0891b2; } .card:nth-child(4n) { background: #ff5a1f; }
</style></head>
<body>
<h1>A wall of cards in grid lanes</h1>
<div class="wall">
  <div class="card" style="height:30mm">1</div><div class="card" style="height:55mm">2</div><div class="card" style="height:22mm">3</div>
  <div class="card" style="height:40mm">4</div><div class="card" style="height:26mm">5</div><div class="card" style="height:48mm">6</div>
  <div class="card" style="height:34mm">7</div><div class="card" style="height:20mm">8</div><div class="card" style="height:44mm">9</div>
</div>
<p>With grid lanes, each card goes into the shortest column, masonry-style; without, the browser ignores <code>display: grid-lanes</code> and the cards stack as blocks.</p>
</body></html>
Default: as stable Chrome
var result = HtmlToPdf.Render(html);
Page 1 of the PDF this code printed
Pages
2
File
55,361 bytes (54.1 KB) · the PDF
ExperimentalWebFeatures = true
var result = HtmlToPdf.Render(html, new HtmlPdfOptions { ExperimentalWebFeatures = true });
Page 1 of the PDF this code printed
Pages
1
File
55,515 bytes (54.2 KB) · the PDF