日本語 | English

ページグループガイド

対象バージョン: Vivliostyle.js v2.39.0+(2025-12-25リリース) 公開日: 2026-05-05 最終更新日: 2026-05-05

このガイドでは、名前付きページと:nth(An+B of C)ページセレクタを解説します。これらを組み合わせることで、同一ファイル内のセクションごとにまったく異なるページレイアウトを与えられるようになります。

なぜ名前付きページが必要か

書籍では、1冊の中で複数のページデザインが必要になることがよくあります:

  • 写真エッセイ章のための、図版に余裕のある幅広レイアウト
  • 用語集のための、狭い2段組レイアウト
  • 表紙や扉のための、フルブリードレイアウト

CSSは@page :left / :right / :firstでページを区別できますが、これらは見開きの左右文書全体の最初のページしか区別しません。今いる章を区別することはできません。名前付きページはその穴を埋めます。

名前付きページの基本

pageプロパティで、ブロックレベルの要素(section、<div>など)をそれが表示されるページの種類の名前を指定します:

section.glossary {
  page: narrow;
}

section.gallery {
  page: wide;
}

そのうえで、対応する@pageルールでスタイルを指定します:

@page narrow {
  size: A5;
  margin: 1.5cm 1cm;
}

@page wide {
  size: A4 landscape;
  margin: 1cm;
}

section.glossaryをレイアウトしたページはnarrowsection.galleryのページはwideを使います。

:nth()ページセレクタ

1つの@page名(または無名のデフォルト)の中で、:nth()は位置でページを選択します:

@page :nth(1)      { /* 最初のページ */ }
@page :nth(odd)    { /* 奇数ページ */ }
@page :nth(even)   { /* 偶数ページ */ }
@page :nth(3n+2)   { /* 2ページ目から3ページごと */ }
@page :nth(-n+3)   { /* 最初の3ページ */ }

An+B形式は:nth-childと同じ規則です。n0, 1, 2, ...を取り、結果が0以下になる場合は無視されます。

ページグループという概念

レイアウトエンジンがページにコンテンツを流し込む過程で、フローボックスに付いたpage名が変わる(例: glossaryの後にgalleryが来る)と、Vivliostyleは強制改ページを発行します。1つの名前付きページブロックから生成された、連続するページの塊がページグループです。

同じpage名の要素が複数続く場合(例:複数のsection.chapter)は、break-before: pageを指定しないと改ページされず、新しいページグループも開始されません。

言い換えれば、ページグループは「同じ@page名を使い、ソースの同じフローレベル領域から生成された、連続するページの並び」です。これが:nth(... of <name>)の選択単位です。

:nth(An+B of C) ―― ページグループのセレクタ(v2.39.0新機能)

Vivliostyle.js v2.39.0は:nth(An+B of <name>)形式に対応しました。インデックスを名前付きページグループに限定します:

@page :nth(1 of body) {
  /* `page: body` を使う各章の最初のページ */
  @top-center { content: none; }
  margin-top: 4cm;
}

@page :nth(odd of body) {
  /* 各 `body` グループ内の奇数位置のページ */
  @bottom-right { content: counter(page); }
}

これにより、「各章の最初のページだけ別デザイン」が簡潔に表現できます。of <name>がないと:nth(1)は文書全体の最初のページしか選べませんが、of <name>を付ければ各グループの最初のページをそれぞれ別個に選択できます。

実践例:章構造のある書籍レイアウト

名前付きページと:nth(... of <name>)を組み合わせた例:

/* ソース構造
   <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; }

/* 各章の扉ページ */
@page :nth(1 of body) {
  @top-center { content: none; }
  margin-top: 4cm;
}

/* 章の2ページ目以降にはランニングヘッダーを表示 */
@page :nth(n+2 of body) {
  @top-center { content: string(chapter-title); }
}

/* 表紙 */
@page cover {
  size: A4;
  margin: 0;
  background: black;
}

このパターンはCSS GCPM 3仕様のExample 13・14で示されており、Vivliostyle.js v2.39.0でネイティブにサポートされるようになりました。

Vivliostyle Viewerでの確認方法

@pageルールはページ分割描画でしか効果が見えません。ページグループ出力を確認するには:

  1. vivliostyle preview(またはnpm run preview)でビルドする
  2. 生成HTMLをVivliostyle Viewerで開く
  3. 「見開き」表示を切り替えて左右ページを確認
  4. 各章が扉ページ用のレイアウトで始まっていることを確認

静的に検証したい場合は、vivliostyle buildを実行して出力PDFを点検します。

参照

  • W3C CSS GCPM 3 §3 Selecting Pages
  • テストケース:
    • vivliostyle.js/packages/core/test/files/named-pages/page-groups.html
    • vivliostyle.js/packages/core/test/files/nth-page/nth-of-page.html