# CSS page breaks for HTML to PDF CSS page breaks for HTML to PDF: force breaks, keep tables and cards together, avoid orphan headings, and set page size with @page. These rules work in any Chromium-based renderer. That includes Chrome's "Save as PDF", Puppeteer, Playwright, Gotenberg and [html-pdf.com](https://html-pdf.com). **Quick answer.** Add `break-before: page` where a new page should start and `break-inside: avoid` on things that must stay whole, then render: ```bash curl https://html-pdf.com/v1/pdf -H "Authorization: Bearer $HTML_PDF_KEY" -H "Content-Type: application/json" \ -d '{"html": "

Page 1

Page 2

"}' -o out.pdf ``` ## Force a new page This rule starts an element on a fresh page. ```css .page-break { break-before: page; } ``` ```html
Cover
Chapter 1
``` `break-before: page` is the modern property. The legacy `page-break-before: always` still works and is a safe fallback. ```css .page-break { page-break-before: always; break-before: page; } ``` Use `break-after: page` to break *after* an element instead. ## Keep things together These rules stop content from being split awkwardly across pages. To keep a card, a table row or a figure on one page, use `break-inside: avoid`. ```css .card, figure, tr, .totals { break-inside: avoid; page-break-inside: avoid; } ``` To keep a heading with the paragraph that follows it, avoid a break after the heading. ```css h2, h3 { break-after: avoid; page-break-after: avoid; } ``` To avoid lonely lines at the top or bottom of a page, set orphans and widows. ```css p { orphans: 3; widows: 3; } ``` ## Repeat table headers on every page This makes long tables readable on every page. Chromium repeats `` automatically when a table spans pages, as long as you use real table markup. ```html …hundreds of rows…
ItemQtyPrice
``` ```css thead { display: table-header-group; } tr { break-inside: avoid; } ``` ## Page size and margins with @page This section sets paper size and margins from CSS. ```css @page { size: A4; margin: 20mm 15mm; } @page :first { margin-top: 40mm; } ``` Chromium only uses the CSS `size` when the renderer is told to prefer it. With html-pdf.com, set `prefer_css_page_size`. ```bash curl https://html-pdf.com/v1/pdf -H "Authorization: Bearer $HTML_PDF_KEY" \ -d '{"html": "

A5 booklet

", "prefer_css_page_size": true}' -o a5.pdf ``` Or skip CSS and pass `format` (`A4`, `Letter`, …), `landscape` and `margin` in the request. Chromium also supports CSS `@page` margin boxes (Chrome 131+), which you can use for running headers and footers. ## Common pitfalls These are the most common reasons page breaks don't behave as expected. - **Breaks ignored inside flex or grid.** Page-break properties apply to block-level boxes in normal flow. Wrap content in plain blocks (`display: block`) where you need breaks. - **Elements with `overflow: hidden` or fixed heights** get clipped instead of flowing to the next page. Let print content grow (`height: auto`). - **Backgrounds missing.** Enable background printing (`print_background`, on by default in html-pdf.com) and add `-webkit-print-color-adjust: exact; print-color-adjust: exact;`. - **Screen styles leaking.** Put print tweaks in `@media print { … }`, because renderers use print media by default. ## Test it in one call You can check your page breaks in seconds. Paste your HTML into the converter on [html-pdf.com](https://html-pdf.com) or call the API. You get 100 free pages, then pay from $0.005 per page, and purchased credits never expire. Next: [headers, footers and page numbers](https://html-pdf.com/pdf-headers-footers-page-numbers). ## FAQ ### How do I force a page break when converting HTML to PDF? Add `break-before: page` (or the legacy `page-break-before: always`) to the element that should start a new page. It works in Chrome, Puppeteer, Playwright, Gotenberg and html-pdf.com. ### How do I stop a table row from splitting across pages? Set `tr { break-inside: avoid; }`. Use real `` markup too, and Chromium repeats the header row on every page. ### Why are my page breaks ignored? Page-break properties only apply to block-level boxes in normal flow, so they're often ignored inside flex or grid containers. Fixed heights and `overflow: hidden` can also clip content instead of letting it flow onto the next page. ### Does the API respect @page size from CSS? Yes, when you set `prefer_css_page_size: true` in the request. Otherwise, pass `format`, `landscape` and `margin` as request options.