Page Groups Guide
Target versions: Vivliostyle.js v2.39.0+ (released 2025-12-25) Published: 2026-05-05 Last updated: 2026-05-05
This guide explains named pages and the :nth(An+B of C) page selector, which together let you give entirely different page layouts to sections within the same document.
Why named pages?
A book often needs more than one page design within a single document:
- A wide, illustration-friendly layout for a photo essay chapter
- A narrow, two-column layout for a glossary
- A full-bleed layout for a cover or a part divider
CSS lets you address pages with @page :left / :right / :first, but those selectors only distinguish facing pages and the very first page — they can't distinguish which chapter you're in. Named pages fill that gap.
Named pages — the basics
The page property specifies the name of the page type on which a flow-level box (a section, a <div>, etc.) will be displayed:
section.glossary {
page: narrow;
}
section.gallery {
page: wide;
}
You then style each named page with a matching @page rule:
@page narrow {
size: A5;
margin: 1.5cm 1cm;
}
@page wide {
size: A4 landscape;
margin: 1cm;
}
Pages produced by laying out section.glossary use the narrow page, while pages produced by section.gallery use the wide page.
The :nth() page selector
Within a single @page name (or the unnamed default), :nth() selects pages by their position:
@page :nth(1) { /* the first page */ }
@page :nth(odd) { /* odd-numbered pages */ }
@page :nth(even) { /* even-numbered pages */ }
@page :nth(3n+2) { /* every 3rd page starting from page 2 */ }
@page :nth(-n+3) { /* the first three pages */ }
The An+B form follows the same convention as :nth-child: n is 0, 1, 2, ..., and any non-positive result is dropped.
The page-group concept
When the layout engine flows content into pages and the page named on the flow box changes (e.g. glossary is followed by gallery), Vivliostyle issues a forced page break. The block of consecutive pages produced by a single named-page block is a page group.
When multiple elements share the same page name (e.g. several section.chapter elements), break-before: page must be specified — without it, no page break occurs and no new page group is started.
In other words, a page group is "a run of pages all using the same @page name, all coming from the same flow-level region in the source." That's the unit :nth(... of <name>) selects within.
:nth(An+B of C) — selectors inside a page group (new in v2.39.0)
Vivliostyle.js v2.39.0 supports the form :nth(An+B of <name>). It restricts the index to within the named page group:
@page :nth(1 of body) {
/* The first page of every chapter using `page: body` */
@top-center { content: none; }
margin-top: 4cm;
}
@page :nth(odd of body) {
/* Odd-positioned pages within each `body` group */
@bottom-right { content: counter(page); }
}
This is what makes "the first page of every chapter looks different from the rest" easy to express. Without of <name>, :nth(1) only selects the very first page of the document; with it, you select the first page of each group separately.
Practical example: a chapter-structured book
Combining named pages and :nth(... of <name>):
/* Source structure */
/*
<section class="cover"> ... </section>
<section class="chapter"> ... </section>
<section class="chapter"> ... </section>
<section class="glossary"> ... </section>
*/
section.cover { page: cover; }
section.chapter { page: body; break-before: page; }
section.glossary { page: narrow; }
/* Per-chapter front page */
@page :nth(1 of body) {
@top-center { content: none; }
margin-top: 4cm;
}
/* Running headers on subsequent chapter pages */
@page :nth(n+2 of body) {
@top-center { content: string(chapter-title); }
}
/* Cover */
@page cover {
size: A4;
margin: 0;
background: black;
}
This pattern is used in CSS GCPM 3 Examples 13 and 14, and is now natively supported in Vivliostyle.js v2.39.0.
Verifying with Vivliostyle Viewer
@page rules only manifest in paginated rendering. To check page-group output:
- Run a build with
vivliostyle preview(ornpm run preview) - Open the generated HTML in Vivliostyle Viewer
- Toggle "Spread" view to see facing pages
- Confirm that each chapter starts with the special opening-page layout
For static verification, run vivliostyle build and inspect the output PDF.
References
- W3C CSS GCPM 3 §3 Selecting Pages
- Test cases:
vivliostyle.js/packages/core/test/files/named-pages/page-groups.htmlvivliostyle.js/packages/core/test/files/nth-page/nth-of-page.html