The PDF renderer turns HTML and CSS into paginated output. This guide covers page layout, typography, tables, charts, and print-specific CSS for invoices, reports, contracts, and certificates.
Page layout
The @page at-rule controls the document’s page structure.
Page size
/* Standard paper sizes */
@page {
size: A4; /* 210mm x 297mm */
}
@page {
size: Letter; /* 8.5in x 11in */
}
@page {
size: Legal; /* 8.5in x 14in */
}
/* Custom dimensions */
@page {
size: 8in 10in; /* Width x Height */
}
/* Landscape orientation */
@page {
size: A4 landscape;
}Margins
Page margins control the printable area and space for headers/footers:
@page {
size: A4;
margin: 2cm; /* All sides equal */
}
@page {
size: Letter;
margin: 1in 0.75in; /* Vertical, Horizontal */
}
@page {
size: A4;
margin: 2cm 1.5cm 2cm 1.5cm; /* Top, Right, Bottom, Left */
}Named pages
Use named pages for different sections of your document:
@page cover {
margin: 0;
}
@page chapter {
margin: 2cm;
@top-center {
content: "Chapter Title";
}
}
.cover-page {
page: cover;
}
.chapter-content {
page: chapter;
}First, left, and right pages
Apply different styles to specific page positions:
/* First page - often no header */
@page :first {
@top-center {
content: none;
}
}
/* Left pages (even) */
@page :left {
margin-left: 3cm;
margin-right: 2cm;
}
/* Right pages (odd) */
@page :right {
margin-left: 2cm;
margin-right: 3cm;
}Page breaks
Force page breaks
/* Break before an element */
.chapter-title {
page-break-before: always;
break-before: page;
}
/* Break after an element */
.section-end {
page-break-after: always;
break-after: page;
}<!-- Force a new page before this element -->
<h1 class="chapter-title">Chapter 2: Advanced Topics</h1>
<!-- Force a new page after this element -->
<div class="section-end">End of Section 1</div>Prevent page breaks
Keep related content together by preventing breaks inside elements:
/* Prevent breaks inside an element */
.keep-together {
page-break-inside: avoid;
break-inside: avoid;
}
/* Common elements to keep together */
figure,
blockquote,
table,
.card,
.info-box {
page-break-inside: avoid;
break-inside: avoid;
}Orphans and widows
Control minimum lines at page boundaries:
p {
orphans: 3; /* Minimum lines at bottom of page */
widows: 3; /* Minimum lines at top of page */
}Page-break rules
/* Headings should stay with following content */
h1, h2, h3, h4, h5, h6 {
page-break-after: avoid;
break-after: avoid;
}
/* Don't break inside list items */
li {
page-break-inside: avoid;
break-inside: avoid;
}
/* Keep images with captions */
figure {
page-break-inside: avoid;
break-inside: avoid;
}Headers and footers
Add running headers and footers using CSS margin boxes within the @page rule.
Basic headers and footers
@page {
size: A4;
margin: 2.5cm 2cm;
@top-left {
content: "Company Name";
font-size: 10pt;
color: #666;
}
@top-right {
content: "Confidential";
font-size: 10pt;
color: #666;
}
@bottom-center {
content: "Page " counter(page) " of " counter(pages);
font-size: 9pt;
}
}Margin boxes
The following margin box positions are available:
| Position | Location |
|---|---|
@top-left | Top margin, left side |
@top-center | Top margin, center |
@top-right | Top margin, right side |
@bottom-left | Bottom margin, left side |
@bottom-center | Bottom margin, center |
@bottom-right | Bottom margin, right side |
@left-top | Left margin, top |
@left-middle | Left margin, middle |
@left-bottom | Left margin, bottom |
@right-top | Right margin, top |
@right-middle | Right margin, middle |
@right-bottom | Right margin, bottom |
Page counters
Use CSS counters for page numbering:
@page {
@bottom-right {
content: "Page " counter(page);
}
}
/* With total page count */
@page {
@bottom-center {
content: counter(page) " / " counter(pages);
}
}Dynamic header text
Use CSS string-set to create running headers:
h1 {
string-set: chapter-title content();
}
@page {
@top-left {
content: string(chapter-title);
}
}First-page headers
@page :first {
@top-left {
content: none; /* No header on first page */
}
@top-right {
content: none;
}
}
@page {
@top-center {
content: "Document Title";
}
}Running elements
The content property in margin boxes accepts strings, counters, and url(). For logos, styled layouts, or other HTML in a header or footer, combine position: running() with element().
Place an HTML element in the document, remove it from normal flow with position: running(name), and reference it from a margin box with content: element(name).
/* Pull element out of the flow */
.running-header {
position: running(headerContent);
}
/* Place it in the page margin */
@page {
margin-top: 3cm;
@top-center {
content: element(headerContent);
}
}<!-- This won't appear inline — it goes straight to the margin box -->
<div class="running-header">
<img src="https://example.com/logo.png" style="height: 20px; vertical-align: middle;" />
<span style="font-size: 10pt; color: #666; margin-left: 8pt;">Company Name</span>
</div>
<h1>Document Title</h1>
<p>Content starts here...</p>Behavior:
- The running element is removed from document flow and does not appear in page content
- It renders in the margin box on every page
- A later element with the same running name replaces it from that page onward
Use that replacement behavior for chapter-specific headers:
.chapter-header { position: running(chapterHead); }
@page {
@top-left {
content: element(chapterHead);
}
}<section>
<div class="chapter-header">Chapter 1: Introduction</div>
<p>Chapter 1 content...</p>
</section>
<section style="break-before: page;">
<!-- Replaces the running header from this page onward -->
<div class="chapter-header">Chapter 2: Analysis</div>
<p>Chapter 2 content...</p>
</section>string-set and running() compared:
| Feature | string-set / string() | running() / element() |
|---|---|---|
| Plain text | Yes | Yes |
| Images / logos | No | Yes |
| Styled multi-element HTML | No | Yes |
| Simpler syntax | Yes | No |
Use string-set for text such as chapter titles. Use running() for logos, icons, or other styled HTML.
Fonts
For predictable output, use a font available to the renderer or embed it in the document.
Web-safe fonts
These web-safe fonts work without embedding:
body {
font-family: Arial, Helvetica, sans-serif;
}
.monospace {
font-family: "Courier New", Courier, monospace;
}
.serif {
font-family: Georgia, "Times New Roman", serif;
}Custom fonts
Embed fonts using @font-face:
@font-face {
font-family: 'CustomFont';
src: url('https://example.com/fonts/custom.woff2') format('woff2'),
url('https://example.com/fonts/custom.woff') format('woff');
font-weight: normal;
font-style: normal;
}
body {
font-family: 'CustomFont', sans-serif;
}Google Fonts CDN
Link to Google Fonts directly in your HTML:
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body>
<h1>Your content</h1>
</body>
</html>Base64-embedded fonts
For offline reliability, embed fonts as base64:
@font-face {
font-family: 'EmbeddedFont';
src: url(data:font/woff2;base64,d09GMgABAAAAAA...) format('woff2');
}Font rules
body {
/* Use a font stack with fallbacks */
font-family: 'Primary Font', 'Fallback Font', sans-serif;
/* Set a readable base size */
font-size: 11pt;
/* Ensure good line spacing */
line-height: 1.5;
/* Enable font smoothing */
-webkit-font-smoothing: antialiased;
}
/* Optimize headings */
h1, h2, h3 {
line-height: 1.2;
page-break-after: avoid;
}Print media queries
Use @media print to apply styles specifically for PDF output:
Basic print styles
/* Screen-only styles */
@media screen {
.print-only {
display: none;
}
body {
background: #f5f5f5;
}
}
/* Print-only styles */
@media print {
.no-print,
.screen-only {
display: none !important;
}
body {
background: white;
color: black;
}
/* Remove decorative elements */
nav,
.sidebar,
.ads,
.social-share {
display: none !important;
}
}Printed links
@media print {
/* Show URL after links */
a[href^="http"]:after {
content: " (" attr(href) ")";
font-size: 0.8em;
color: #666;
}
/* But not for image links or internal links */
a[href^="#"]:after,
a:has(img):after {
content: none;
}
/* Remove link styling */
a {
color: inherit;
text-decoration: underline;
}
}Print layout adjustments
@media print {
/* Use full width */
.container {
max-width: 100%;
margin: 0;
padding: 0;
}
/* Flatten multi-column layouts */
.grid {
display: block;
}
/* Ensure images don't overflow */
img {
max-width: 100%;
height: auto;
}
/* Reset background colors */
* {
background: transparent !important;
}
}Tables
Tables need explicit break and header rules when they span pages.
Basic table styling
table {
width: 100%;
border-collapse: collapse;
page-break-inside: auto;
}
thead {
display: table-header-group; /* Repeat header on each page */
}
tfoot {
display: table-footer-group; /* Repeat footer on each page */
}
tbody {
display: table-row-group;
}
tr {
page-break-inside: avoid; /* Keep rows together */
break-inside: avoid;
}Repeating table headers
Repeat table headers on every page:
<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
<tbody>
<tr><td>Data 1</td><td>Data 2</td><td>Data 3</td></tr>
<!-- More rows... -->
</tbody>
</table>thead {
display: table-header-group;
background: #f0f0f0;
}
th {
font-weight: bold;
text-align: left;
padding: 8px;
border-bottom: 2px solid #333;
}Long tables
/* Allow table to break across pages */
table.long-table {
page-break-inside: auto;
}
/* But keep individual rows together */
table.long-table tr {
page-break-inside: avoid;
break-inside: avoid;
}
/* Minimum height prevents tiny orphan rows */
table.long-table td {
min-height: 2em;
}Zebra striping
tbody tr:nth-child(even) {
background-color: #f9f9f9;
}
@media print {
tbody tr:nth-child(even) {
background-color: #f0f0f0 !important;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}Table borders
table {
border: 1px solid #ccc;
}
th, td {
border: 1px solid #ccc;
padding: 8px 12px;
}
/* Handle borders at page breaks */
@media print {
table {
border-collapse: collapse;
}
tr {
border-bottom: 1px solid #ccc;
}
}Charts
The PDF renderer does not execute JavaScript. Chart.js, D3.js, Plotly.js, Highcharts, and ApexCharts therefore produce no output, and <canvas> elements remain blank. Render charts as static SVG or images before adding them to the HTML.
Inline SVG
SVG is the recommended format because it stays sharp at any zoom level:
<div class="chart">
<h4>Revenue by Quarter</h4>
<svg viewBox="0 0 400 220" xmlns="http://www.w3.org/2000/svg">
<rect x="30" y="120" width="50" height="80" fill="#3498db" rx="2"/>
<rect x="110" y="60" width="50" height="140" fill="#3498db" rx="2"/>
<rect x="190" y="30" width="50" height="170" fill="#2ecc71" rx="2"/>
<rect x="270" y="50" width="50" height="150" fill="#2ecc71" rx="2"/>
<text x="55" y="215" text-anchor="middle" font-size="11" fill="#333">Q1</text>
<text x="135" y="215" text-anchor="middle" font-size="11" fill="#333">Q2</text>
<text x="215" y="215" text-anchor="middle" font-size="11" fill="#333">Q3</text>
<text x="295" y="215" text-anchor="middle" font-size="11" fill="#333">Q4</text>
<line x1="20" y1="200" x2="340" y2="200" stroke="#666" stroke-width="1"/>
<line x1="20" y1="0" x2="20" y2="200" stroke="#666" stroke-width="1"/>
</svg>
</div>Embedded images
When SVG isn’t available, use base64-encoded or hosted images:
<!-- Base64 encoded -->
<img src="data:image/png;base64,iVBORw0KGgo..."
alt="Revenue Chart"
style="width: 100%; max-width: 600px;" />
<!-- Hosted URL -->
<img src="https://example.com/charts/revenue-q4.png"
alt="Revenue Chart"
style="width: 100%; max-width: 600px;" />Chart styles
.chart {
break-inside: avoid;
page-break-inside: avoid;
margin: 1cm 0;
text-align: center;
}
.chart svg,
.chart img {
max-width: 100%;
height: auto;
}
/* SVG text doesn't inherit document fonts */
.chart svg text {
font-family: Arial, Helvetica, sans-serif;
fill: #333;
}Plotly with Python
In a Python script, server, or code interpreter, Plotly can export publication-quality charts as static SVG without a browser:
import plotly.graph_objects as go
import plotly.io as pio
import base64
# Create a chart
fig = go.Figure(data=[
go.Bar(x=["Q1", "Q2", "Q3", "Q4"], y=[120, 180, 240, 200],
marker_color="#3498db")
])
fig.update_layout(
title="Quarterly Revenue",
width=600, height=350,
margin=dict(l=40, r=20, t=50, b=40),
font=dict(family="Arial, sans-serif", size=12)
)
# Export as inline SVG (preferred)
svg_str = pio.to_image(fig, format="svg").decode("utf-8")
# Or as base64 PNG
png_b64 = base64.b64encode(
pio.to_image(fig, format="png", scale=2)
).decode("utf-8")Then embed in your HTML template:
<!-- SVG (preferred — sharp at any resolution) -->
<div class="chart">{svg_str}</div>
<!-- Or base64 PNG -->
<div class="chart">
<img src="data:image/png;base64,{png_b64}"
alt="Quarterly Revenue"
style="width:100%; max-width:600px;" />
</div>Plotly requires the
kaleidopackage for static export:pip install plotly kaleido
Other rendering options
| Approach | Description |
|---|---|
| Server-side SVG | Generate SVG strings with D3 (Node.js) or matplotlib (Python) and embed inline |
| JS library export | Use Chart.js .toBase64Image(), Plotly .toImage(), or D3 .node().outerHTML before sending HTML to the API |
| Static image API | Use services like QuickChart.io to generate chart images via URL |
| matplotlib / seaborn | Save as SVG with plt.savefig(buf, format='svg') and embed the SVG string |
Chart issues
- A
<canvas>stays blank because it requires JavaScript. Use SVG or<img>instead. - SVG
<text>elements do not inherit document fonts. Setfont-familyandfont-sizeexplicitly. - Use
viewBoxfor responsive SVG scaling instead of fixed pixel dimensions. - Wrap charts in a container with
break-inside: avoidso they do not split across pages. - Use high-contrast print colors instead of transparency or subtle gradients.
PDF bookmarks
PDF bookmarks create a clickable outline in the viewer sidebar. Use -pdfmcp-bookmark-* properties to build it from document headings:
/* Map headings to bookmark levels */
h1 { -pdfmcp-bookmark-level: 1; -pdfmcp-bookmark-state: open; }
h2 { -pdfmcp-bookmark-level: 2; -pdfmcp-bookmark-state: closed; }
h3 { -pdfmcp-bookmark-level: 3; }
/* Custom label text */
h1 { -pdfmcp-bookmark-label: content(text); }
/* Custom label for appendix sections */
.appendix h2 {
-pdfmcp-bookmark-level: 1;
-pdfmcp-bookmark-label: "Appendix: " content(text);
}
/* Exclude decorative headings */
.no-bookmark { -pdfmcp-bookmark-level: none; }| Property | Values | Description |
|---|---|---|
-pdfmcp-bookmark-level | none, 1-6 | Depth in the PDF outline |
-pdfmcp-bookmark-label | content(text), content(before), content(), custom string | Display text |
-pdfmcp-bookmark-state | open, closed | Whether children are expanded |
Cross-references
Use target-counter() to insert the page number of an element by its id in a “see page X” reference or table of contents:
a.page-ref::after {
content: " (page " target-counter(attr(href), page) ")";
}<p>For more details, see <a class="page-ref" href="#results">Results</a>.</p>
<!-- Renders: "For more details, see Results (page 12)." -->Footnotes
CSS footnotes automatically move marked content to the bottom of the current page with auto-numbering:
.footnote { float: footnote; }
::footnote-call {
content: counter(footnote);
font-size: 0.7em;
vertical-align: super;
line-height: none;
}
::footnote-marker {
content: counter(footnote) ". ";
font-weight: bold;
}
/* Optional rule above footnotes */
@page {
@footnote {
border-top: 1px solid #ccc;
padding-top: 0.5em;
}
}<p>Studies confirm this finding.<span class="footnote">Smith et al., 2024.</span></p>The footnote text moves to the page bottom with automatic superscript numbering in both places.
Hyphenation
Automatic hyphenation improves justified text by breaking long words at syllable boundaries:
body {
hyphens: auto;
-webkit-hyphens: auto;
}Requirement: Set the lang attribute on <html> for the hyphenation dictionary to load:
<html lang="en">Combine it with text-align: justify to reduce uneven spacing in justified paragraphs.
Preserve backgrounds
Background colors are stripped by default in print rendering. Force them to appear with print-color-adjust:
body {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}
/* Or target specific elements */
.colored-badge {
background: #e74c3c;
color: white;
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}Box decoration across pages
When an element with borders or backgrounds splits across a page boundary, box-decoration-break: clone repeats the full decoration on each fragment:
.info-box {
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
border: 2px solid #3498db;
padding: 1em;
background: #f0f8ff;
}Without clone (the default slice behavior), the top fragment loses its bottom border and the bottom fragment loses its top border at the page break.
Table of contents
Combine leader() and target-counter() to create classic TOC entries with dot fills:
.toc a {
text-decoration: none;
color: inherit;
display: block;
}
.toc a::after {
content: leader(".") target-counter(attr(href), page);
}
.toc .level-2 { padding-left: 1.5em; }
.toc .level-3 { padding-left: 3em; }<nav class="toc">
<a class="level-1" href="#intro">Introduction</a>
<a class="level-2" href="#background">Background</a>
<a class="level-1" href="#methods">Methods</a>
</nav>This renders as:
Introduction ............ 1
Background ............ 3
Methods ................. 5You can use different fill characters: leader("."), leader("-"), leader("_"), or leader(" ").
CSS support
Paged PDF rendering supports a subset of CSS:
| Feature | Support | Notes |
|---|---|---|
| CSS Grid | Supported for simple cases | Test complex grids and page breaks |
| Flexbox | Partial | Basic flex works; avoid for page-level structure |
| CSS Variables | Supported | var(--color) works normally |
| Gradients | Supported | linear-gradient, radial-gradient |
calc() | Supported | Works in all contexts |
| 2D Transforms | Supported | rotate(), scale(), translate() |
| 3D Transforms | Not supported | No perspective, rotateX/Y/Z |
| Box Shadow | Not supported | Use borders or background colors instead |
| Border Radius | Supported | Works normally |
| Opacity | Supported | Works normally |
| Animations | Not supported | Static rendering only |
| JavaScript | Not executed | No <script>, no dynamic rendering |
position: fixed | Supported | Fixed elements repeat across pages |
position: sticky | Not supported | Use thead { display: table-header-group; } |
| Viewport units | Not supported | No vw/vh; use mm, cm, in, pt |
Use block and inline layout, floats, tables, or basic flexbox. Use CSS Paged Media properties such as @page, break-*, and margin boxes for print behavior.
Invoice example
This invoice combines the page, font, table, and print rules from the guide:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Invoice #12345</title>
<style>
@page {
size: A4;
margin: 2cm 1.5cm;
@top-right {
content: "Invoice #12345";
font-size: 9pt;
color: #666;
}
@bottom-center {
content: "Page " counter(page) " of " counter(pages);
font-size: 8pt;
color: #999;
}
}
@page :first {
@top-right {
content: none;
}
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Helvetica Neue', Arial, sans-serif;
font-size: 11pt;
line-height: 1.5;
color: #333;
}
.header {
display: flex;
justify-content: space-between;
margin-bottom: 2cm;
page-break-inside: avoid;
}
.company-info h1 {
font-size: 24pt;
color: #2563eb;
margin-bottom: 0.5em;
}
.invoice-details {
text-align: right;
}
.invoice-number {
font-size: 14pt;
font-weight: bold;
}
.addresses {
display: flex;
justify-content: space-between;
margin-bottom: 1.5cm;
}
.address-block {
width: 45%;
}
.address-block h3 {
font-size: 10pt;
text-transform: uppercase;
color: #666;
margin-bottom: 0.5em;
border-bottom: 1px solid #ddd;
padding-bottom: 0.25em;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 1cm;
}
thead {
display: table-header-group;
}
th {
background: #f8f9fa;
font-weight: 600;
text-align: left;
padding: 12px;
border-bottom: 2px solid #dee2e6;
}
td {
padding: 12px;
border-bottom: 1px solid #eee;
}
tr {
page-break-inside: avoid;
}
.text-right {
text-align: right;
}
.totals {
margin-left: auto;
width: 250px;
page-break-inside: avoid;
}
.totals-row {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #eee;
}
.totals-row.total {
font-weight: bold;
font-size: 14pt;
border-bottom: 2px solid #333;
border-top: 2px solid #333;
padding: 12px 0;
}
.notes {
margin-top: 2cm;
padding: 1cm;
background: #f8f9fa;
border-radius: 4px;
page-break-inside: avoid;
}
.notes h4 {
margin-bottom: 0.5em;
}
@media print {
.no-print {
display: none;
}
}
</style>
</head>
<body>
<div class="header">
<div class="company-info">
<h1>ACME Corp</h1>
<p>123 Business Street</p>
<p>City, State 12345</p>
<p>contact@acme.com</p>
</div>
<div class="invoice-details">
<p class="invoice-number">Invoice #12345</p>
<p>Date: January 15, 2025</p>
<p>Due: February 15, 2025</p>
</div>
</div>
<div class="addresses">
<div class="address-block">
<h3>Bill To</h3>
<p><strong>Client Company</strong></p>
<p>456 Client Avenue</p>
<p>City, State 67890</p>
</div>
<div class="address-block">
<h3>Ship To</h3>
<p><strong>Client Company</strong></p>
<p>456 Client Avenue</p>
<p>City, State 67890</p>
</div>
</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Qty</th>
<th class="text-right">Unit Price</th>
<th class="text-right">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>Professional Services</td>
<td>10</td>
<td class="text-right">$150.00</td>
<td class="text-right">$1,500.00</td>
</tr>
<tr>
<td>Software License</td>
<td>1</td>
<td class="text-right">$499.00</td>
<td class="text-right">$499.00</td>
</tr>
<tr>
<td>Support Package</td>
<td>1</td>
<td class="text-right">$99.00</td>
<td class="text-right">$99.00</td>
</tr>
</tbody>
</table>
<div class="totals">
<div class="totals-row">
<span>Subtotal</span>
<span>$2,098.00</span>
</div>
<div class="totals-row">
<span>Tax (10%)</span>
<span>$209.80</span>
</div>
<div class="totals-row total">
<span>Total</span>
<span>$2,307.80</span>
</div>
</div>
<div class="notes">
<h4>Notes</h4>
<p>Payment is due within 30 days. Please include invoice number with your payment.</p>
</div>
</body>
</html>Rendering notes
General
- Preview PDF output throughout development.
- Use
ptfor font sizes andcmorinfor margins. - Keep layouts simple enough to paginate predictably.
- Include fallback fonts and graceful degradation.
Performance
- Inline critical CSS to avoid external stylesheet requests.
- Size images for their intended output; use base64 for small graphics.
- Limit external resources because each one adds latency.
Accessibility
- Use enough contrast for text to remain readable in print.
- Keep body text at 10pt or larger.
- Use semantic HTML to preserve meaningful content flow.
Common issues
| Issue | Solution |
|---|---|
| Content cut off at page edges | Set adequate page margins |
| Headers/footers overlap content | Ensure margin boxes don’t exceed margin size |
| Tables split awkwardly | Use display: table-header-group on thead |
| Images overflow pages | Set max-width: 100% and page-break-inside: avoid |
| Fonts not rendering | Use web-safe fonts or embed via @font-face |
| Colors not printing | Add print-color-adjust: exact |
Quick reference
CSS properties
/* Page setup */
@page { size: A4; margin: 2cm; }
/* Page breaks */
page-break-before: always | avoid | auto;
page-break-after: always | avoid | auto;
page-break-inside: avoid | auto;
/* Modern alternatives */
break-before: page | avoid | auto;
break-after: page | avoid | auto;
break-inside: avoid | auto;
/* Paragraph control */
orphans: 3;
widows: 3;
/* Table headers */
thead { display: table-header-group; }
/* Color printing */
print-color-adjust: exact;
-webkit-print-color-adjust: exact;Page sizes
| Size | Dimensions (mm) | Dimensions (inches) |
|---|---|---|
| A4 | 210 x 297 | 8.27 x 11.69 |
| A5 | 148 x 210 | 5.83 x 8.27 |
| Letter | 216 x 279 | 8.5 x 11 |
| Legal | 216 x 356 | 8.5 x 14 |
| Tabloid | 279 x 432 | 11 x 17 |
Related documentation
- HTML to PDF: convert HTML through the API
- API reference: endpoint documentation
- Quick start: make the first request in five minutes