Vivliostyle.js における CSS Paged Media の実装

2021-04-10
Shinyu Murakami
Vivliostyle Foundation

目次

  1. CSS組版エンジン Vivliostyle.js Core
    1. Vivliostyle.js のアイデア since 2014
    2. CSS組版に必要なCSS仕様は?
    3. 再開発途上 CSS Paged Media サポート
  2. CSS Paged Media を使いこなそう!
    1. Named strings—柱を本文の見出しから
    2. Named pages—名前付きのページルール
    3. Nth page selector: nth()
  3. ページメディア用CSS仕様サポート状況まとめ
    1. CSS Paged Media Level 3
    2. CSS Generated Content for Paged Media (GCPM)
    3. CSS Fragmentation Level 3
    4. CSS Page Floats
    5. より詳しくは Vivliostyle ドキュメント→「サポートする CSS 機能」へ

CSS組版エンジン Vivliostyle.js Core

Vivliostyle.js のアイデア since 2014

CSS組版に必要なCSS仕様は?

Vivliostyle.js はWebブラウザを利用する。
したがってWeb用のCSS仕様は基本的に利用できる。
ページメディア用のCSS仕様サポートを追加すればよい🌟

そうして Vivliostyle.js 開発がスタート 👉Vivliostyle のなりたち

再開発途上 CSS Paged Media サポート

Vivliostyle.js にはだいぶ前からページメディア用のCSS仕様の多くの機能が実装済み。(初期の開発者たちに感謝🙏)

しかし、いくつかの重要な機能が実装されずに残っていた。

🐢やっと昨年末から、ぼちぼち実装を進めることができている。

🌟最新バージョンで利用可能になったページメディア用CSS機能:

CSS Paged Media を使いこなそう!

Named strings—柱を本文の見出しから

名前付き文字列(Named strings)の使用例:

@page :right {
  @top-right {  /* 右上のページヘッダに章見出し */
    content: string(chap-title, first-except); /* 章の先頭ページを除き表示 */
  }
}
h1.chapter { /* 章見出し */
  string-set: chap-title content();
}
h1.chapter[title] {
  string-set: chap-title attr(title); /* 属性の値を使うことも可能 */
}

Named pages—名前付きのページルール

ページの種類ごとに名前をつけてページ設定を定義。 例:

@page cover { /* 名前付きのページ設定(名前: "cover") */
  margin: 0;  /* "cover" ページは余白無しに */

  /* "cover" ページは柱(ページヘッダー)無しに */
  @top-left { content: none; }
  @top-right { content: none; }
}

.cover {
  page: cover;  /* pageプロパティで使用する名前付きページを指定 */
}

Nth page selector: nth()

文書の N 番目のページのスタイルを定義することなどできます。

構文: @page :nth(An+B)
(CSS セレクタ :nth-child(An+B) のページ版のようなもの)

例:

@page :nth(1) {
  margin: 0;
  background-image: url(cover.png);
}

複数HTML文書連結の場合の @page :first@page :nth(1) の違い

複数HTML文書をまとめて1つの本(PDF、WebPub)にする場合:

  • @page :first は全体の先頭ページだけに適用
    • これは Vivliostyle の以前からの動作仕様。現在の CSS Paged Media 仕様には、複数のHTML文書をまとめて1つの本にする場合のことは定義されていないため、独自仕様といえる。
  • @page :nth(1) は、各HTML文書の先頭ページに適用

つまり、章ごとにファイルを分けている場合、@page :nth(1) は各章の先頭ページに適用、 @page :first は全体の先頭ページだけ。

名前付きページと :nth() の組み合わせの例

@page :first { /* 全体の一番最初のページのみに適用 */
  counter-reset: chapter;
}
@page chapter:nth(1) { /* 各章ファイルの最初のページに適用 */
  counter-increment: chapter;
}
h1::before {
  content: "第" counter(chapter) "章";
}
.chapter {
  page: chapter;
}

各章のHTMLは次のようになってるとする:

<body>
  <section class="chapter">
    <h1>章のタイトル</h1>
    ...
  </section>
</body>

これにより、章カウンタを全体の先頭でリセット、各章の先頭でインクリメントすることができる。

注意: もし複数の章を1つのHTMLファイルにしている場合は、 @page chapter:nth(1) は各章ではなくて1つのHTMLファイルの先頭ページだけに適用される。

ページメディア用CSS仕様サポート状況まとめ

CSS Paged Media Level 3

https://www.w3.org/TR/css-page-3/

CSS Generated Content for Paged Media (GCPM)

https://www.w3.org/TR/css-gcpm-3/

CSS Fragmentation Level 3

https://www.w3.org/TR/css-break-3/

CSS Page Floats

https://www.w3.org/TR/css-page-floats-3/

より詳しくは Vivliostyle ドキュメント→「サポートする CSS 機能」へ