# 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
```
`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
| Item | Qty | Price |
…hundreds of rows…
```
```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.