Headers and footers
One header, one footer
Section titled “One header, one footer”A document can define one header and one footer band, repeated on every page:
doc.Header(h => h.Text("Northwind Studio Ltd | 12 Harbour Lane | London EC1V 4AB", Small)) .Footer(f => f.Text("Northwind Studio Ltd | VAT ID GB123456789", Small));Text runs, styles, and links work exactly like in paragraphs - including fluent inline styling:
doc.Footer(f => f .Text("Generated with ") .Link("Papyra", "https://papyra.rocks", Small) .Text(" - page footer").FontSize(8).Italic());Rich bands: rows, tables, images
Section titled “Rich bands: rows, tables, images”Headers and footers are full bands - besides text runs they take rows, tables, images, and lines, so a logo-plus-page-number layout is one call:
doc.Header(h => h .Row(row => row .FixedItem(110f, p => p.Image(logoBytes)) .RelativeItem(p => p.Text("Quarterly Report", Title))) .Line(0.75f));Text runs and blocks mix freely; runs written before a block flush into their own paragraph first, so composition order is preserved.
A different first page
Section titled “A different first page”FirstPageHeader/FirstPageFooter replace the regular band on page one - a title-page layout without giving up the running header:
doc.Header(h => h.Text("Running header")) .FirstPageHeader(h => h.Text("TITLE PAGE", Big)); // page 1 onlydoc.FirstPageHeader(h => { }); // or: no header on page 1DOCX maps this to native w:titlePg first-page header/footer parts; the XLSX print header uses differentFirst. The layout reserves the taller of the two bands on every page, so the content area stays uniform.
Page numbers and dynamic fields
Section titled “Page numbers and dynamic fields”Headers and footers can carry dynamic fields, resolved at render time:
doc.Footer(f => f .Span("Muster GmbH - ", Small) .PageXofY(Small)); // "Page 3 of 12"
doc.Header(h => h .Span("Rendered ") .RenderDate("dd.MM.yyyy")); // date, invariant culture, default yyyy-MM-ddPageXofY(style) is shorthand for Span("Page ") + PageNumber() + Span(" of ") + TotalPages() - the individual builder methods compose freely with static runs and alignment styles. The render date comes from Metadata.CreationDate when set, otherwise the actual render time.
Per-format behavior:
- PDF - the band is re-laid-out for every page, so centered or right-aligned footers stay exactly positioned as the digits change, and the total is correct even when tables split across pages.
- DOCX - page fields become native Word
PAGE/NUMPAGESfields that Word recomputes on open (viewers that never recompute fields show the cached value1). The render date is literal text. - XLSX - a field-bearing header/footer becomes a native print header/footer (
&P/&Ncodes) instead of sheet rows, visible in print preview and page-layout view; per-run font styling is not carried into it.
Fields also work in body content - paragraphs, table cells, list items, and row items (only footnote bodies reject them). PDF resolves the exact values with a bounded second layout pass, so doc.Paragraph(p => p.Text("This document has ").TotalPages().Span(" pages.")) prints the real total even when tables split across pages; DOCX emits its native fields anywhere; HTML and XLSX have no page concept in flowing content, so they drop body page fields and print only the render date as literal text.
Keep field-bearing bands short: the band’s height is fixed once (with a two-digit page-count placeholder), so a footer that would wrap onto an extra line at very high page counts can overlap content. In XLSX, a field-bearing band maps to the print header, which can only carry text - combining page fields with tables or images in one band fails the XLSX render.
Format behavior
Section titled “Format behavior”Headers and footers repeat per page in PDF and DOCX. XLSX has no pages; static band content becomes the first rows of the sheet and static footer content the last rows, band images float as anchored drawings, and field-bearing bands move to the print header/footer (see above) - where the first-page variant applies via differentFirst. The grid-row route has no first-page concept.
For table-level repetition - column headers repeating when a table spans pages - see tables.
© 2026 Stefan Nikolei. Payments are processed by Paddle.com as merchant of record.