Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ページ分割

sghtmltopdfはCSS Fragmentationのプロパティでページ分割を制御します。

明示的な改ページ

.chapter { break-before: page; }   /* この要素の前で改ページ */
.summary { break-after: page; }    /* この要素の後で改ページ */
.card    { break-inside: avoid; }  /* この要素をページ境界で割らない */
プロパティ受け付ける値
break-before / break-afterauto / avoid(avoid-page・avoid-columnも同義) / always(pageも同義)
break-insideauto / avoid(同上)

古いpage-break-before / page-break-after / page-break-insideもエイリアスとして受け付けます。 wkhtmltopdfやwicked_pdf向けに書いた資産をそのまま持ち込めます。

left/right/recto/verso(見開き制御)と多段組み関連の値は非対応です。

CSSを書かずに指定する

HTML属性でも書けます。

<div data-page-break="before">…</div>
<div data-page-break="after">…</div>
<div data-page-break="avoid">…</div>

こちらは弱い優先度のヒントとして扱われるので、スタイルシートのルールで個別に上書きできます。

段落が泣き別れないようにする

p {
  orphans: 3;   /* ページ末尾に最低3行は残す */
  widows: 3;    /* 次ページの先頭に最低3行は送る */
}

1以上の整数で、初期値はどちらも2です。 指定を満たせない場合は段落ごと次のページへ送られます。

@page — 用紙とページ余白

@page {
  size: A4;
  margin: 20mm;

  @top-center    { content: "請求書"; }
  @bottom-center { content: counter(page) " / " counter(pages); }
}

@page :first {
  @bottom-center { content: "表紙"; }
}
  • sizeはページサイズのキーワード(A4/Letter等)・<length>{1,2}・landscape/portraitを受け付けます
  • CLIのページ設定オプションより@pageが優先されます(CLI側は初期値)
  • margin box(@top-left-corner〜@bottom-right-cornerの16種)にはcontentでテキストを置けます。背景色や枠線などの装飾は非対応です
  • counter(page)は現在のページ番号、counter(pages)は総ページ数です

@pageの制約

  • size/marginはページごとに変えられません。:first/:left/:right付きのsize/margin宣言はパースされますが適用されず、これらの擬似クラスは margin boxの 内容の出し分けにだけ使えます
  • 名前付きページ(@page introとpage: intro)は非対応です
  • margin boxの寸法は簡略化しています。4隅は縦横マージンの交差部分で固定、残り12個は各辺を3等分した均等割りです(width指定は無視されます)
  • counter(pages)はストリーミングモードでは使えません(総ページ数が1パスでは決まらないため)

CLIの--header-centerなどのオプションは、内部的にこの@pageのmargin boxへマップされます。 両方書いた場合はCSSが勝ちます。

テーブルのページ分割

1ページに収まらないテーブルは行単位で分割され、複数ページへ流れます。

  • <thead>の行は2ページ目以降の先頭に繰り返されます。複数行の見出しにも対応し、1ページに収まる表では複製しません
  • <tfoot>はソース順に関わらずテーブル末尾へ移動しますが、各ページ下端への繰り返しは行いません(最終ページに1回だけ出ます)
  • captionはcaption-sideに従って、最初(top)または最後(bottom)の断片に付きます
  • 各断片はテーブル自身の背景・枠線を引き継ぎ、border-collapse: collapseの枠線統合もページ内でそのまま効きます

既知の限界として、rowspanが分割点をまたぐセルは開始行の断片に属し、下部がページからはみ出します(クリップされません)。 行単位のbreak-inside: avoidとorphans/widows相当も未対応です。

FlexboxとGridの扱い

レイアウトページ分割
display: flex収まればアトミック(途中で分割せず、次ページへ送る)。1ページに収まらない高さのコンテナは、縦に重ならないアイテム群(列flexなら各アイテム、折り返す行flexなら各flex line)を単位に分割し、アイテムが1つだけの帯はブロックと同様に内部でも分割する
display: grid行単位で分割する(複数行にまたがるアイテムがある境界では分割しない)
display: table行単位で分割する(上記)

大きなカードを並べる用途では、flexコンテナが丸ごと次ページへ飛ぶことがあります。 分割してほしい場合はGridかテーブルを使ってください。

1ページに収まらないflexコンテナ(列flexで組んだ文書本文など)は、はみ出した部分を失わずに後続ページへ流れます。 折り返さない行flexで1ページより高いflex lineは分割できず、はみ出します(クリップされません)。

よく使う書き方

見出しが単独でページ末尾に残らないようにする:

h2, h3 {
  break-after: avoid;   /* 見出しの直後で改ページしない */
  break-inside: avoid;
}

明細の1件が2ページに割れないようにする:

.line-item { break-inside: avoid; }

章ごとに必ず改ページする:

section.chapter + section.chapter { break-before: page; }

Note

ストリーミングモードでは:last-childなどの後方参照セレクタが常に非マッチになります。 上の例の+(隣接兄弟)は使えます。