CSS Paged Media: The Complete Guide

Everything you need to know about the CSS Paged Media Module—from @page rules and page breaks to margin boxes and named pages. Style documents for print and PDF generation using pure CSS.

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:

Together, these specs give you fine-grained control over how HTML content is paginated, numbered, and laid out across physical or virtual pages.

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

  1. Write your document as semantic HTML.
  2. Style it with CSS, including @page rules for page size, margins, and orientation.
  3. Use fragmentation properties (break-before, break-inside) to control where pages break.
  4. Add running headers and footers with margin boxes.
  5. 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:

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.