What Is CSS Paged Media?
CSS Paged Media is a set of CSS properties defined in the W3C CSS Paged Media Module Level 3 specification. While regular CSS targets continuous media (scrollable web pages), Paged Media targets paged output—documents that are split into discrete pages, such as printed paper or PDFs.
The specification introduces the @page at-rule, which lets you control page dimensions, margins, orientation, page breaks, headers, footers, and page counters entirely through CSS. Instead of relying on PDF libraries or complex templating engines, you write standard HTML and CSS and let the rendering engine handle pagination.
Paged Media CSS is part of a family of related specifications:
- CSS Paged Media Module Level 3 — the
@pagerule, page size, margins, page selectors - CSS Fragmentation Module Level 3 —
break-before,break-after,break-inside, orphans, widows - CSS Generated Content for Paged Media — margin boxes (
@top-center,@bottom-right, etc.), running headers, page counters
Together, these specs give you fine-grained control over how HTML content is paginated, numbered, and laid out across physical or virtual pages.
How It Relates to Printing & PDF Generation
Every time you hit Ctrl+P (or ⌘P) in a browser, the rendering engine switches from continuous layout to paged layout. Your @page rules kick in, @media print styles apply, and the content is sliced into pages. The same mechanism powers headless PDF generation.
With a headless browser API—like Doppio—you can send HTML and CSS to a cloud rendering engine and receive a pixel-perfect PDF back. This means you can use the same CSS Paged Media properties to generate invoices, reports, contracts, certificates, or any paginated document programmatically.
The Typical Workflow
- Write your document as semantic HTML.
- Style it with CSS, including
@pagerules for page size, margins, and orientation. - Use fragmentation properties (
break-before,break-inside) to control where pages break. - Add running headers and footers with margin boxes.
- Generate the PDF via
window.print(), a headless browser, or an API like Doppio.
Quick Example: A Basic @page Setup
Here is a minimal CSS Paged Media setup that configures an A4 document with 20mm margins and a footer showing the page number:
@page {
size: A4 portrait;
margin: 20mm;
@bottom-center {
content: "Page " counter(page) " of " counter(pages);
font-size: 9pt;
color: #666;
}
}
@media print {
body {
font-family: Georgia, serif;
font-size: 12pt;
line-height: 1.6;
}
h1 {
break-after: avoid;
}
table, figure {
break-inside: avoid;
}
}
This tells the browser (or headless renderer) to create A4 pages, add 20mm margins on all sides, print a page counter in the bottom center margin box, and prevent headings from being orphaned at the bottom of a page.
Browser Support Overview
Browser support for CSS Paged Media varies significantly. Chromium-based browsers (Chrome, Edge, Opera) have the most complete implementation. Safari has improved support since version 18.2. Firefox remains limited.
| Feature | Chrome 131+ | Safari 18.2+ | Firefox 133+ |
|---|---|---|---|
@page rule |
Yes | Yes | Partial |
size descriptor |
Yes | Yes | No |
| Page break properties | Yes | Yes | Yes |
| Named pages | Yes | Partial | No |
Margin boxes (@top-center, etc.) |
Yes | No | No |
counter(page) / counter(pages) |
Yes | Partial | Partial |
:first / :left / :right selectors |
Yes | Partial | Partial |
marks / bleed |
Partial | No | No |
Because Doppio uses a Chromium-based rendering engine, all the features covered in this guide work reliably when generating PDFs through the API. If you need cross-browser print support, consider a polyfill like Paged.js.
What This Guide Covers
This guide is split into focused chapters. Each page is a complete reference for its topic.
| Chapter | What You'll Learn |
|---|---|
| The @page Rule | The size descriptor (A4, letter, custom), margins, orientation, page-orientation, marks, and bleed. Every property you can set inside @page { }. |
| Page Breaks | break-before, break-after, break-inside, orphans, widows, and the legacy page-break-* properties. How to control exactly where pages split. |
| Named Pages & Selectors | The page property, named @page rules, and pseudo-class selectors (:first, :left, :right, :blank). How to apply different layouts to different sections of a document. |
| Margin Boxes & Page Numbers | The 16 margin box regions (@top-left, @bottom-center, etc.), page counters (counter(page), counter(pages)), running headers with string-set and running(). |
| Native CSS vs Paged.js | When native CSS Paged Media is enough and when you need the Paged.js polyfill. Feature comparison, trade-offs, performance, and recommendations. |
When to Use Native CSS vs Paged.js
If you are generating PDFs server-side with a Chromium-based renderer (like Doppio), native CSS Paged Media is the best choice. You get full support for @page, margin boxes, page counters, named pages, and fragmentation properties without any JavaScript overhead.
Use Paged.js when you need:
- Cross-browser print preview in the browser (Firefox, Safari)
- Features not yet implemented in any browser (e.g., footnotes, advanced running headers)
- A visual in-browser paginated preview for your users
For a detailed feature-by-feature comparison, see Native CSS vs Paged.js.
Generate PDFs with Doppio
Doppio is an API for generating PDFs and screenshots from HTML/CSS using a headless Chromium renderer. All CSS Paged Media properties covered in this guide work out of the box. Send your HTML (with @page rules, margin boxes, and page breaks), and Doppio returns a production-ready PDF.
curl -X POST https://api.doppio.sh/v1/render/pdf/direct \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"page": {
"pdf": {
"printBackground": true,
"preferCSSPageSize": true
},
"goto": {
"url": "https://your-site.com/invoice/42"
}
}
}'
Set preferCSSPageSize: true to let your @page { size: ... } rule control the output dimensions instead of the default US Letter size.