Page Numbers

Page numbers in EuroPDF are a single CSS rule. Behind it sits the full toolkit of CSS Paged Media counters: “Page X of Y”, lowercase Roman numerals for front matter, per-chapter resets, and page references inside a table of contents that resolve at render time.

Page numbers live inside header and footer slots, so they compose freely with everything covered in Headers & Footers — logos, chapter titles, mixed page sizes, and the rest.

A complete example

▶ Open in Playground
<style>
  @page {
    size: A4;
    margin: 2.5cm 2cm;
    @bottom-right {
      content: "Page " counter(page) " of " counter(pages);
      font-size: 9pt;
      color: #888;
    }
  }

  /* Front matter uses lowercase roman numerals */
  @page front {
    @bottom-right { content: counter(page, lower-roman); }
  }

  /* No page number on the cover */
  @page :first {
    @bottom-right { content: none; }
  }

  section.front-matter { page: front; page-break-after: always; }
  body { counter-reset: page 1; }  /* restart numbering for body */

  /* TOC entries resolve to the actual page each anchor lives on */
  ul.toc a::after {
    content: leader('.') ' ' target-counter(attr(href), page);
  }
</style>

Try it now

Test it instantly in the Playground — no sign-up required.

More examples

“Page X of Y”

▶ Open in Playground
@page {
  @bottom-right {
    content: "Page " counter(page) " of " counter(pages);
  }
}

Both counters are populated automatically — no second pass needed.

Roman numerals for front matter

▶ Open in Playground
@page front {
  @bottom-center { content: counter(page, lower-roman); }
}

section.front-matter { page: front; }
body { counter-reset: page 1; }   /* restart at 1 for body */

Use upper-roman, lower-alpha, decimal-leading-zero, or any other CSS list-style value.

Restart numbering at each chapter

▶ Open in Playground
h1.chapter { counter-reset: page 1; }

@page {
  @bottom-center { content: counter(page); }
}

Each chapter starts at page 1 — useful for technical manuals split into independent sections.

“Chapter 2 — Page 3”

▶ Open in Playground
body  { counter-reset: chapter; }
h1.chapter {
  counter-increment: chapter;
  counter-reset: page 1;
}

@page {
  @bottom-center {
    content: "Chapter " counter(chapter) " — Page " counter(page);
  }
}

Combine a custom counter for chapters with the built-in page counter.

Auto-resolved page numbers in a table of contents

▶ Open in Playground
ul.toc a::after {
  content: leader('.') ' ' target-counter(attr(href), page);
}

target-counter() resolves each anchor at render time. Reorder content, add chapters — the TOC stays accurate.

“See page 17” in body text

▶ Open in Playground
<p>For details on the API, see page <a href="#api-reference" class="pageref"></a>.</p>
a.pageref::after { content: target-counter(attr(href), page); }

Cross-references inside paragraphs work with the same mechanism.

The full header/footer slot system (sixteen margin boxes, dynamic chapter titles, logos, mixed page sizes) lives on Headers & Footers. Page counters compose with everything there.


EuroPDF wraps PrinceXML — the full reference for counters and generated content lives in the Prince user guide.