CSS 組版やってみた!

やましー @yamasy1549

本稿は、viola-savepdf (Viola, Vivliostyle) を用いて CSS 組版を行った際の流れや感想を書いたものです。

はじめに

はじめまして、やましーといいます。特に仕様に詳しいとかはなくて、ただの一般 CSS ユーザーです。TeX が色々と面倒だったのがきっかけで、学校のレポート等を CSS 組版で書いたりしています。

本稿では、まず筆者の CSS 組版経験、組版環境を説明します。それから、viola-savepdf を用いて同人誌と卒論を制作した際の感想を述べます。組版ツール開発者ではない、いちユーザーからの目線で紹介できたらいいなと思っています。

筆者の CSS 組版経験

CSS 組版に初めて触れたのは 2016 年頃です。最初の頃は Vivliostyle の存在も知らず、当時のブラウザ実装がカバーしている範囲でスタイルを作っていました。これは筆者が下手だったのですが、印刷用スタイルの知見がなく明示的にページを宣言する必要があるなど、一応組版は可能なものの実用的ではありませんでした。とはいえ、学校の薄いレポート程度ならこれでも充分に要件を満たしていました。今はもう残骸しかありませんが、yamasy1549/ZinkeNhttps://github.com/yamasy1549/ZinkeNというリポジトリで見ることができます。

しばらくは ZinkeN を使っていたのですが、2018 年にはるさめさんの『CSS ではじめる同人誌制作 増訂版https://pentapod.booth.pm/items/969754』を読んで、技術書典 5 に出した同人誌https://kosen14s.booth.pm/では本格的に CSS 組版に挑戦することになりました。

また、この同人誌を CSS 組版で書けたことが嬉しかったので、卒論も CSS 組版で制作することにしました。

同人誌TOGETHER見本
同人誌TOGETHER見本
卒論見本
卒論見本

CSS 組版の流れ

おおむね以下のような構成、環境をとっています。

Untitled-1.png (76.2 kB)

ソースコード群のサンプルは https://github.com/yamasy1549/nitac-tex-template/5年_卒論 にあります。

スタイルを生成する

基本的な要素のスタイルを決めます。まずは以下のような要素を考えておけば、大体の要求はカバーできるでしょう。実際にコンテンツを書き始めてから「これも必要だった!」と気づくことも多いですが……。

改ページについては arinoth さんの記事『EPUB Adaptive Layout による段組み混在レイアウトへの挑戦』の『「超」重要な改ページの制御』、村上真雄さんの記事『Vivliostyle Viewer で CSS 組版ちょっと入門』の『改ページの指定』に詳細な説明があります。

要素 HTML タグ名、クラス名の例 設定するスタイルの例
章見出し h1 直前で改ページ
節見出しなど h2-h6 直後での改ページ回避
段落 p.left.right.center テキストの両端揃え、左右中央揃えオプション
打ち消し del 打ち消し線
下線 .underline 下線
強調 strong 太さ
リンク a
figureimg 要素内での改ページ回避
table 罫線
図表キャプション figcaptioncaption
引用 blockquote
箇条書き oluldl マーカー(点、連番など)

次に、CSS カウンターを用いて番号を振ります。以下のようなカウンターを用意すると良いでしょう。箇条書きのリスト番号もカウンターで管理するのは、list-styleでは(1)などの括弧付き連番マーカーが設定できないためです。

用途 カウンター名の例 カウンター表示場所の例
章節番号など chaptersection h1-h6、目次
図番号 figure figcaption、参照文中
表番号 table caption、参照文中
脚注番号 footnote 脚注、参照文中
箇条書きのリスト番号 list 箇条書きのリスト
参考文献番号 ref 参考文献のリスト、参照文中

文章構造を生成する

Pug を採用しました。HTML タグの括弧を書かないのでレビュー時に文章が見やすいことと、要素にクラスを付与したりスタイルを直書きしたりしても記法が変わらないこと(候補にマークダウンがあったが、マークダウン記法に HTML 記法が混ざるのがあまり好きではない)が理由です。

また、PDF 生成時に数式の表示やシンタックスハイライトの有効化を行うため、ここで前処理をします。Pug の filter 機能を用いて、Pug 形式で書かれた数式を MathJax 形式に、コードブロックを Prism.js 形式に変換します。詳細な例は割愛しますが、文字列を受け取って決められたクラスを持つ要素の中に入れる、という処理になります。

スタイルと文章構造の生成は、gulp で該当ファイルを監視し、ファイルの保存をトリガーとして生成を行い、結果をブラウザで確認する、という流れになります。

PDF を生成する

コマンドひとつで HTML から PDF を生成できる viola-savepdfhttps://github.com/violapub/viola-savepdfを採用しました。同人誌は複数人による合作で、構成ファイル数が多く、PDF 生成は CLI で操作できることが望ましいという条件があったためです。

CSS 組版 (viola-savepdf, Viola, Vivliostyle) の手触り

同人誌や卒論の制作に CSS 組版を用いた感想です。

よかったところ

  1. 人によっては学習コストが低い
    Web アプリケーション開発などで CSS を触ったことのある人なら、新しい方法を覚えることなく、同じようにスタイルを作成できます。また先人が GitHub でサンプルを公開している場合もあるため、あまり時間をかけずに CSS 組版環境を準備できます。簡単な PDF を吐くだけのために、ン GB もするツールをインストールする必要もありません。
  2. ブラウザでスタイルのデバッグができる
    以前は TeX を使っていたのですが、スタイルを変更したい場合、どの要素にどのようなスタイルが当たっているか知ることは困難でした。CSS 組版ならブラウザの開発者ツールですぐに確認できるため、スタイルを自分好みに変更しやすく、自由度が上がります。
  3. 手元に環境を作らなくても、頑張れば PDF の確認ができる
    これは CSS 組版に限った話ではないのですが、便利だったので紹介します。複数人による同人誌制作では Web フロントエンド開発に慣れていない人もおり、全員が手元に環境を用意できるわけではありませんでした。そこで Pug 形式で書いたファイルを GitHub に push すれば、CI が回って PDF を生成し、Google Drive にアップロードされる、という仕組みを用意しました。これで各人が自分の書いた記事の出力を確認できるようになりました。

こまったところ

  1. 脚注と他の要素が被ってしまう?
    ソースコードブロック等がうまく脚注を回避できず、脚注と重なって表示されてしまうことがありました。適宜手動でpage-breakを設定する必要がありました。
  2. PDF のビルドが重い?
    計測比較は行っておらず体感ですが、画像、カウンター、ページ数が多いとビルドに要する時間が多くなりました。同人誌 70 ページ強は 60 秒くらいでした。
  3. 特殊なページの処理が難しい?
    同人誌の表紙を作りたかったのですが、画像をページ全面に隙間なく表示することが難しく、別に表紙だけの PDF を作って手動で結合する必要がありました。現在はこちらのプルリクにて修正されています(https://github.com/vivliostyle/vivliostyle.js/pull/514)。
  4. 特殊なページ数の表示制御が難しい?
    卒論で「表紙はページ番号なし、2〜3 ページ目は目次なので専用のページ番号、4 ページ目以降からメインのページ番号を数え始めたい」場合にちょっと詰まりました。Vivliostyle で使っているカウンターpageは単純に最初のページから番号を数えていて、ユーザー側では上書きできないようです。従ってこれとは別に、以下のように目次専用ページ番号tocやメインのページ番号pを準備する必要がありました。
@page {
  // 目次のページ番号とメインのページ番号のカウンター
  counter-increment: toc p;
  // 目次は2ページ目から、本論は4ページ目から始まるので
  // 1ページ目の時点で逆算しておく
  &:first {
    // 試していないけど、上手くやれば -1 や -3 などの直指定をやめられそう
    counter-reset: toc -1 p -3;
  }
}

@-epubx-page-master {
  @-epubx-partition {
    // 1ページ目は表紙なのでページ番号なし
    -epubx-enabled: -epubx-expr(page-number == 1);
    content: "";
  }

  @-epubx-partition {
    // 2ページ目から3ページ目までは目次専用のカウンターを用いる
    -epubx-enabled: -epubx-expr(page-number > 1 && page-number < 4);
    content: counter(toc, lower-roman);
  }

  @-epubx-partition {
    // 4ページ目以降は本論のページ番号
    -epubx-enabled: -epubx-expr(page-number > 3);
    content: counter(p);
  }
}

おわりに

CSS 組版をやってみた感想を書きました。「こまったところ」は筆者の CSS の書き方が良くなかったりするかもしれません、解決策をご存知の方は是非シェアしていただけると嬉しいです。

便利なツールが増え次第に広まりつつある CSS 組版ですが、細かい tips や事例の公開は少なく、まだまだこれからという印象があります。本稿が CSS 組版の需要を示す事例のひとつになれば幸いです。