CSS page breaks for PDF: control where pages start and end
The modern break properties, when to use each, and patterns for tables, headings and cards.
When HTML becomes a PDF, the browser has to decide where each page ends. Left alone, it will happily split a table row, strand a heading at the bottom of a page or cut a card in half. CSS gives you three properties to guide those decisions.
The three properties
| Property | Use it to | Typical value |
|---|---|---|
break-before | Start an element on a new page | page |
break-after | Force a new page after an element, or avoid one | page or avoid |
break-inside | Keep an element on one page if it fits | avoid |
The older page-break-before, page-break-after and page-break-inside properties still work in Chromium as aliases, so existing templates don’t need rewriting. Use the modern names for new work.
Start sections on a new page
.chapter { break-before: page; }
.chapter:first-of-type { break-before: auto; } /* no blank first page */In our tests the converter ignores a forced break before the very first element, so page one is never left empty; the second rule is a harmless safeguard for other print tools.
Keep headings with what follows
h1, h2, h3 { break-after: avoid; }avoid is a request, not a guarantee. If keeping things together is impossible, the browser breaks anyway rather than losing content.
Stop cards, figures and rows splitting
figure, .card, blockquote, tr { break-inside: avoid; }This works well for elements shorter than a page. An element taller than a page must split; there is nowhere else for it to go.
Long tables
Chromium repeats a table’s <thead> at the top of every printed page the table spans, so readers never lose the column names. Put header cells in <thead> rather than the first body row:
<table>
<thead><tr><th>Date</th><th>Item</th><th>Amount</th></tr></thead>
<tbody>
<tr><td>1 Oct</td><td>Design work</td><td>£400.00</td></tr>
…
</tbody>
</table>
<style>
tr { break-inside: avoid; }
</style>Orphans and widows
For paragraphs, orphans and widows set the minimum number of lines left at the bottom or carried to the top of a page. The default is 2; raising it to 3 gives text a more typeset look:
p { orphans: 3; widows: 3; }Why a break might be ignored
- Flex and grid containers. Breaks between items inside some flex or grid layouts are handled less predictably than in normal block flow. If a break isn’t honoured, try a block layout inside
@media print. - Absolutely positioned or floated elements. These sit outside normal flow, so break rules don’t apply to them in the usual way.
- Fixed heights and
overflow: hidden. A container clipped to a height can hide content that would have flowed onto the next page.
Next: the print CSS checklist covers margins, backgrounds and hiding screen-only elements.