Current status
Headers and footers go in native @page margin boxes (see
below), including @page :first/
:left/:right overrides, with page numbers via
counter(page). CSS fixed positioning (position: fixed) repeats
content on every page inside the page area, for overlays such as a corner badge. Tables spanning multiple pages continue correctly, and the
<thead> row repeats at the top of every continuation page automatically.
CSS fixed positioning
Use position: fixed to place content at a fixed position on every rendered
page. As in Chrome (CSS 2.1 §10.1), its containing block is the page area inside the
@page margins: top: 0 / bottom: 0 sit on the content
area's edges, and anything outside the page area is clipped. To draw in the margins, use the
@page margin boxes (@top-center, @bottom-right, ...) or the
fluent Header()/Footer(), which are placed against the whole sheet.
(Before 2.0, EggPdf placed author fixed boxes against the whole sheet.)
@page
margin boxes below (sized by @page margin-top/margin-bottom) or the
fluent Header()/Footer().
<style>
.badge {
position: fixed;
top: 0; right: 0; /* top-right corner of the page area */
font-size: 9px;
color: #b91c1c;
}
</style>
<div class="badge">CONFIDENTIAL</div>Page numbers with counter(page) (works today)
counter(page) and counter(pages) resolve per physical page inside a
position: fixed element's content and in margin boxes — put them in a ::after (or
::before) rule rather than as literal element text, since a real page number
isn't known until the whole document is paginated:
.badge::after {
content: " · page " counter(page) " of " counter(pages);
}Each physical page gets its own resolved number — no manual per-page text needed.
Large tables spanning pages (works today)
A <table> taller than one physical page correctly continues onto as
many additional pages as it needs — no rows are lost or painted off-page, regardless of
table size:
<table>
<thead>
<tr>
<th>Invoice #</th>
<th>Date</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<!-- rows continue onto additional pages as needed -->
</tbody>
</table>
The <thead> row itself repeats at the top of every continuation page
automatically — no extra markup needed.
@page margin boxes
Headers and footers can also use standard CSS @page margin box syntax —
the same as Chrome's print stylesheet support. All 16 margin-box positions are
supported (@top-left/-center/-right,
@bottom-left/-center/-right, the four
-corner boxes, and the six @left-*/@right-* side
boxes), with content (literal strings, counter(page),
counter(pages), attr()) plus basic font-size,
color, font-family and font-weight styling:
@page {
margin: 2cm 2cm 3cm 2cm; /* extra bottom space for footer */
@top-center {
content: "My Document";
font-size: 9pt;
color: #666;
}
@bottom-center {
content: "Page " counter(page) " of " counter(pages);
font-size: 8pt;
}
}
@page :first {
@top-center { content: none; } /* no header on the first page */
}
@page :first, :left and :right page-selector
scoping is also supported, for margin-box content only: :first overrides
apply to physical page 1, :left/:right alternate on even/odd
pages after that (a margin box with no override for the current page type falls back to
the base @page rule). Page size and margin declarations on
a selector-scoped rule are not applied — this engine lays out in a single pass, so a
different page size per page type isn't supported yet.