# Pagination basics

> Control page breaks, keep blocks together, repeat table headers and fix the usual pagination problems in HTML to PDF output.



A PDF is your HTML poured into fixed-size pages. Chromium decides where the content breaks, and CSS fragmentation properties let you steer those decisions. This page collects the rules that matter for documents, and the fixes for the problems that come up most often.

The page box comes from the [PDF options](/docs/pdf-options#page-setup): `paper`, `orientation` and `margin`, or from your CSS `@page` rule when `prefer_css_page_size` is on.

## Force a page break [#force-a-page-break]

Break before or after an element with CSS:

```css
.chapter { break-before: page; }
.cover { break-after: page; }
```

Or insert a break from the template, which is easier inside loops:

```jinja
{% for certificate in certificates %}
  <section class="certificate">…</section>
  {% if not loop.last %}{{ page_break() }}{% endif %}
{% endfor %}
```

Note the `loop.last` check: a break after the final element produces an empty last page.

## Keep content together [#keep-content-together]

`break-inside: avoid` moves an element to the next page instead of splitting it:

```css
.totals,
.signature-block,
figure,
tr {
  break-inside: avoid;
}
```

An element taller than one page will still be split: there is nowhere else to put it.

## Keep a heading with its content [#keep-a-heading-with-its-content]

`break-after: avoid` asks for no break directly after an element:

```css
h2, h3 { break-after: avoid; }
```

The most reliable approach is to wrap the heading and the first block that must stay with it:

```html
<div style="break-inside: avoid">
  <h2>Payment details</h2>
  <p>Please transfer the total to the account below within 30 days.</p>
</div>
```

## Tables [#tables]

Long tables are the main source of pagination problems. Three rules cover most of it:

```css
thead { display: table-header-group; }
tfoot { display: table-footer-group; }
tr { break-inside: avoid; }
```

* `thead` repeats the header row at the top of every page the table spans. Put the header cells in a real `<thead>` element, not in the first `<tbody>` row.
* A `tfoot` group repeats at the bottom of every page, so keep grand totals in a block after the table if they should appear only once.
* `tr { break-inside: avoid; }` keeps a row's cells on one page. Rows with a lot of text can still break if a single row is taller than the page.

## Orphans and widows [#orphans-and-widows]

Stop single lines being left behind at the bottom or top of a page:

```css
p { orphans: 3; widows: 3; }
```

## Page size in CSS [#page-size-in-css]

By default the `paper`, `orientation` and `margin` options define the page. With `prefer_css_page_size: true`, the size from your CSS wins, which also allows different sizes within one document using named pages:

```css
@page { size: A4; }
@page wide { size: A4 landscape; }

.appendix-table { page: wide; }
```

Keep setting margins through the `margin` option, so that headers and footers and your margins stay in sync.

## Single-page output [#single-page-output]

`single_page: true` produces one page as tall as the content, with the paper width you set. It is the usual choice for receipts on narrow paper and for continuous documents that will be read on screen:

```json
{ "paper": { "width": "80mm", "height": "200mm" }, "single_page": true }
```

## Common problems and fixes [#common-problems-and-fixes]

| Symptom                                      | Likely cause                                                           | Fix                                                                                                                                                                                                                  |
| -------------------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Table rows split across pages                | Rows may break by default                                              | `tr { break-inside: avoid; }`                                                                                                                                                                                        |
| Header row only on the first page            | Header cells are in `tbody`, or `display` was overridden               | Use `<thead>` with `display: table-header-group`                                                                                                                                                                     |
| Empty page at the end                        | A break after the last element, or a full-height element               | Skip the break for the last item, avoid `height: 100vh` and fixed full-page heights                                                                                                                                  |
| Heading alone at the bottom of a page        | No keep-with-next rule                                                 | `break-after: avoid`, or wrap heading and first paragraph in a `break-inside: avoid` container                                                                                                                       |
| Body text hidden behind the header or footer | Margin smaller than the header or footer `height`                      | Increase `margin.top` or `margin.bottom`; check the render's warnings                                                                                                                                                |
| Background colours or images missing         | Backgrounds aren't printed                                             | Set `print_background: true` and `print-color-adjust: exact` on the element                                                                                                                                          |
| The PDF looks different from the browser     | Print styles are applied                                               | Check your `@media print` rules, or render with `emulate_media: "screen"`                                                                                                                                            |
| Wrong or fallback fonts                      | The font isn't bundled with the engine, or its file couldn't be loaded | Use the engine's bundled fonts, or declare `@font-face` in the head with a reachable source. The browser falls back without a warning, but a font file that couldn't be loaded shows up as an `asset_failed` warning |
| Content cut off on the right                 | Fixed widths wider than the printable area                             | Printable width is the paper width minus both margins, for example 180 mm on A4 with 15 mm margins. Use percentages and `box-sizing: border-box`.                                                                    |
| Flex or grid sections break oddly            | Fragmentation of flex and grid containers is limited                   | Use block layout or tables for long, paginated content                                                                                                                                                               |
| Unexpectedly many pages                      | Long data, oversized images or forced breaks                           | Check the render's `pages` count; a PDF over your plan's page limit fails with `page_limit_exceeded`                                                                                                                 |

## Page numbers [#page-numbers]

Page numbers belong in the header or footer, where the renderer fills in the current and total page numbers. See [Headers and footers](/docs/headers-and-footers).

## Pagination toolkit [#pagination-toolkit]

Renders of code and Markdown templates, and of HTML or Markdown you send, load a small pagination stylesheet that covers the same ground with less CSS. Pages rendered from a URL don't get it.

**Print defaults.** Table header and footer groups repeat on every page. Table rows, images, SVGs and figures aren't split. Paragraphs, list items and quotes keep at least three lines at the bottom and top of a page, and headings stay with what follows them. The defaults sit in a CSS cascade layer, so any rule of your own overrides them.

**Utility classes.** Add them to elements in your template:

| Class                                             | Effect                                                                              |
| ------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `.dda-keep-together`                              | Don't split the element across pages                                                |
| `.dda-keep-with-next`                             | No page break directly after the element                                            |
| `.dda-page-break-before`, `.dda-page-break-after` | Start a new page before or after the element                                        |
| `.dda-avoid-row-split`, `.dda-allow-row-split`    | On a table or a row: keep rows on one page, or let them break                       |
| `.dda-repeat-header`, `.dda-no-repeat-header`     | On a table: repeat the header row on every page, or print it once                   |
| `.dda-orphans-widows`                             | Keep at least three lines at the bottom and top of a page                           |
| `.dda-print-only`, `.dda-screen-only`             | Show the element only in print, as in PDFs, or only on screen                       |
| `.dda-fill-page`                                  | Fill the remaining page height, for example to push a signature block to the bottom |

**Pagination check.** The editor's PDF preview flags table rows and images split across pages, tables that continue without their header, table footers such as totals that print on every page, headings at the bottom of a page, elements wider than the printable area, unbreakable blocks taller than a page, and blank or nearly blank last pages. Most findings come with a one-click fix that adds CSS to the template's head.

Still planned:

* `.dda-running-title`, which repeats the current section's title in the header
* an optional paged-media mode for features Chromium lacks, such as running elements, tables of contents with page references, and footnotes
