PDFPipe

The page box / @top-center and the margin boxes

How to put a running header in a PDF with CSS

The page margin boxes are sixteen named regions around the page box, such as @top-center and @bottom-right, each of which can hold generated content that repeats on every page.

What it is for

This is the specification's answer to running headers and footers, and it is elegant: the header is CSS, it lives with the rest of the document's styling, and it can pull text from the content with string-set.

Support: Does nothing in a browser-based render

Not implemented by browser engines. Writing @top-center produces no error and no header. Dedicated print engines like PrinceForm and WeasyPrint do implement it, which is why so much writing about it exists and so little of it works in a browser-based render.

What to write instead

The specification syntax is shown first so it is recognisable, followed by the approach that produces the result you were after.

css
/* The specification version. Silent no-op in a browser-based render. */
@page {
  @top-center { content: "Statement for March 2026"; }
  @bottom-right { content: counter(page) " of " counter(pages); }
}

/* What works: header and footer templates passed with the render, styled
   entirely inline because they get none of the document's CSS. */
{
  "options": {
    "displayHeaderFooter": true,
    "margin": { "top": "20mm", "bottom": "18mm" },
    "headerTemplate": "<div style=\"font-size:9pt;padding:0 16mm;color:#555\">Statement for March 2026</div>",
    "footerTemplate": "<div style=\"font-size:9pt;padding:0 16mm;text-align:right\">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span></div>"
  }
}

The mistake people make

Spending an afternoon on this before discovering it is not implemented. The tell is that nothing appears and nothing errors, which is what unimplemented CSS always looks like.

Frequently asked

Does @top-center and the margin boxes work when generating a PDF?

Does nothing in a browser-based render. Not implemented by browser engines. Writing @top-center produces no error and no header. Dedicated print engines like PrinceForm and WeasyPrint do implement it, which is why so much writing about it exists and so little of it works in a browser-based render.

How would I know if it were not working?

You would not, from the CSS. Unimplemented and unmatched CSS both fail silently, which is why the reliable test is to set a deliberately extreme value and see whether anything changes. If a 40mm margin looks the same as an 18mm one, the rule is not reaching the page.

Related properties

Things that come up in the same part of a document stylesheet.

Paste the CSS and see what the rendered page does with it.