HTML to PDF page breaks: tables and print CSS

An HTML preview does not expose every print-layout problem. This example generates a multi-page report and an appendix. Use it to check page boundaries with the same data and renderer as your integration.

Static demonstration PDF, rendered from the files below with Chromium. All data is fictional.

Requirements

  • Download report-template.html and report-data.json below. The data contains 60 fictional rows, including longer descriptions.
  • API generation requires a Templatr key and available quota. You can view the sample PDF without an account.

1. Define the paper and content boundaries

@page selects A4 with 18 mm margins. Do not set a fixed page height on body: let content flow onto the next page. Templatr’s renderer respects CSS @page dimensions.

break-inside: avoid on tr asks the renderer to keep a row together. thead repeats the table heading. break-after: avoid discourages orphaned headings; break-before: page starts the appendix on a new page.

A row taller than a page cannot remain intact: shorten it or allow it to split. Do not apply break-inside: avoid to an entire table that needs multiple pages.

html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>{{report.title}}</title>
  <style>
    @page { size: A4; margin: 18mm; }
    body { font: 11pt Arial, sans-serif; color: #172033; }
    h1 { font-size: 24pt; }
    h2 { break-after: avoid; }
    table { width: 100%; border-collapse: collapse; }
    thead { display: table-header-group; }
    th, td { border-bottom: 1px solid #dbe2ea; padding: 3mm; text-align: left; }
    tr, .summary { break-inside: avoid; }
    td { overflow-wrap: anywhere; }
    th:first-child, td:first-child { width: 22mm; white-space: nowrap; }
    th:last-child, td:last-child { width: 25mm; white-space: nowrap; }
    .appendix { break-before: page; }
  </style>
</head>
<body>
  <h1>{{report.title}}</h1>
  <p>{{report.period}}</p>
  <table>
    <thead><tr><th>Reference</th><th>Description</th><th>Amount</th></tr></thead>
    <tbody>{{ items loop }}<tr><td>{{item.reference}}</td><td>{{item.description}}</td><td>{{item.amount}}</td></tr>{{ end loop }}</tbody>
  </table>
  <div class="summary"><h2>Summary</h2><p>{{report.summary}}</p></div>
  <section class="appendix"><h2>Appendix</h2><p>This section starts on a new page. All values are fictional.</p></section>
</body>
</html>
Download report-template.html

2. Use data that spans more than one page

The preview below shows two rows; the download contains 60, enough rows to check repeated headings and page boundaries. Change the descriptions and add a long unbroken word to check overflow-wrap. The JSON array order determines row order.

json
{
  "report": {
    "title": "Monthly activity report",
    "period": "September 2026",
    "summary": "60 demonstration rows. All amounts are display values calculated before rendering."
  },
  "items": [
    {
      "reference": "DEMO-001",
      "description": "Integration review and document layout testing",
      "amount": "EUR 25.00"
    },
    {
      "reference": "DEMO-002",
      "description": "Integration review and document layout testing",
      "amount": "EUR 25.00"
    }
  ]
}
Download report-data.json

3. Generate the report

Set TEMPLATR_API_KEY, upload the template, then replace TEMPLATE_ID_FROM_RESPONSE with the returned template_id. curl sends the JSON file unchanged and saves the PDF response.

bash
export TEMPLATR_API_KEY='YOUR_API_KEY'
curl --fail-with-body "https://api.templatr.app/upload" \
  -H "Authorization: Bearer $TEMPLATR_API_KEY" \
  -F "[email protected]" \
  -F "name=Example report"
export TEMPLATR_TEMPLATE_ID='TEMPLATE_ID_FROM_RESPONSE'
curl --fail-with-body "https://api.templatr.app/pdf/$TEMPLATR_TEMPLATE_ID?format=pdf" \
  -H "Authorization: Bearer $TEMPLATR_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @report-data.json --output report.pdf

Checks and troubleshooting

  • Check that DEMO-001 through DEMO-060 each appear once, in order.
  • On intermediate pages, check the Reference, Description and Amount headings and make sure content does not overlap the margins.
  • The appendix should start on its own page. Total page count depends on fonts and the length of your data.
  • If a table is clipped horizontally, reduce column widths or unbreakable content. Keep background colors in the template CSS; the renderer has background printing enabled.
  • Remote images and external fonts may be blocked. This example uses a system font with no scripts or network resources.
Read API quotas and limits

Continue learning