研究会発表でのプレゼンを想定して、スライドをHTML…というかMarkdownとCSSで作る場合の嬉しいところをピックアップして、CSSの使い方を見てみます。
Markdown→HTML→CSSでプレゼンという処理系はいくつかあって、同じCSSの手法がそのまま使えるとは限りません。この記事ではVivliostyle12を想定します。
想定する状況は次のようなものです。まず、学会の研究会での発表ならば元になる論文/予稿があって、主張をテキストで表現できているところからスライド作りが始まると思います。また、ヘッダーやフッターに挿入する項目(「日付」、「研究会名」、など)や書式(「スライド番号/総スライド数」、など)が研究室などで指導されていたりもします。
この記事のサンプルは次の通りです:
- スライドのPDF: slide.pdf
- スライドをVivliostyleで表示
- スライドの原稿:
- Markdown: slide.md
- 図: figure/
- サンプルスライドのための個別CSS: author.css
- 用意されていたテーマCSS: theme.css
Vivliostyleを使ってサンプルを試す方法は、記事の最後「サンプルを試す」で説明します。
テキストの回り込み
HTML+CSSでは図にfloat
プロパティを設定して、テキストが図を回り込むのが普通で、特に工夫はいりません。プレゼン・アプリだと改行を手作業で入れたりテキスト・ボックス全体の幅を狭くしたりして調整するところです。
「◯にA」の図はcircle.svg
というSVGファイルで、次のMarkdownで挿入されています。
{style="float-reference: page; float: block-start inline-end;"}
改行位置の調整
CSSでは自動的に折り返される改行の位置を、word-break
プロパティ5を使って調整できます。
既定値のword-break: normal;
という設定では、普通の規則で改行します:
word-break: auto-phrase;
という設定では、日本語として、より自然な位置で改行します:
auto-phrase
の効果については好みが分かれるかもしれません。
なお、サンプルのスライド全体には、試しにword-break: auto-phrase;
と設定しています。
文字数が均等になるような改行
先頭スライド/カバー・スライドのタイトルは文字も大きいので1行に収まらないことがあります。そんなときに、前記のように自然な位置で改行して、かつ、各行がほぼ同じ長さになるよう調整してもらうこともできます。
先頭スライドのタイトルが、次のようなMarkdownだとします。タイトルには改行が入っていません。
# Markdownでスライドを書いてVivliostyleで組んでプレゼン #
CSSの設定で、自動的に次のように改行させられます。
CSSの設定は次のとおりです:
-
word-break: auto-phrase;
で、ことばとして自然なところで改行します -
text-wrap: balance;
6で、行の文字数が均等になるように改行します
約物の前後の空白の詰め
"「"や"("といった約物が行頭・行末にきたり連続したりする場合の空白の詰めを,
text-spacing-trim
プロパティ78で制御できます。
text-spacing-trim: normal;
で、行頭の約物は詰めませんが、約物が連続するときに詰めます。これが既定値です。
text-spacing-trim: trim-both;
と設定すると、行頭行末や連続する約物の空白を詰めます。
text-spacing-trim: space-all;
と設定すると、約物の空白を詰めません。前の2つと比べてみてください。
スライドはテキストが短く箇条書きも多いので、テキストのまとまりは行頭の揃えで見せるのがよいかもしれません。
サンプルのスライドは、全体にtext-spacing-trim: trim-both;
と設定しています
ヘッダーとフッター
スライド本文から次のようなテキストを抜き出して、ヘッダーやフッターに表示できます:
- 発表のタイトル(
h1
要素)やセクションの見出し(##
見出し、つまりh2
要素など)といった既定のタグの付いたテキスト - 日付、発表者、研究会名など既定のタグが付いていないテキスト
また、総スライド数を数えてくれて、その値を自動生成するテキストに含められます。
ヘッダー/フッターはCSSのマージン・ボックス
ヘッダーやフッターを表示するには、CSSのマージン・ボックスを利用します。マージン・ボックスは、@top-left
や@bottom-right-corner
など、側面とコーナーの合計16個の場所が定義されています91011。
スライド本文のテキストを抜き出して表示
スライド本文から所定のテキストを自動的に抜き出してヘッダーやフッターに表示できると、本文を修正したときの修正漏れを防げます。
これには、CSSの名前付き文字列(named string12)という仕組みを使います。
やり方は大まかに次の手順です:
- 抜き出したいテキストに印を付ける。
「印が付く」=「セレクターで選べる」です - その印を手がかりとしてテキストに名前を付ける
- その名前を使って、表示したい場所にテキストを生成する
次の順に説明します:
- 発表のタイトルやセクションの見出し
- 発表のタイトル、日付、発表者、研究会名など
発表のタイトルやセクションの見出し
発表タイトルにはh1
、セクションの見出しにはh2
といったHTML既定の印(タグ)を付けます。h2
見出しを、(自動生成した)番号付きで各スライドの@top-right
マージンに表示するとしてみましょう。
それにはCSSのstring-set
プロパティを使って、生成した番号に、例えばchapter-number
という名前を、テキストにchapter
という名前を付けます。
h2 {
string-set: chapter-number content(before), chapter content();
}
content(before)
はh2
の::before
疑似要素の内容を示します。::before
疑似要素に番号を生成してる想定です。content()
はcontent(text)
という意味で、h2
のテキストを示します。
そして、@top-right
マージンのcontent
プロパティの値で、string
関数の中でこれらの名前を使ってテキストを参照します。first
は、そのスライド(ページ)中の最初の見出しを使います; 見出しが2つあったら最初のものを使うということです。
@page {
@top-right { content: string(chapter-number, first) " " string(chapter, first); }
}
これでスライドの右上に、番号付きで見出しが表示されます。このスライドは「6.3 発表の…」ですが、1つ上位の「6. ヘッダーとフッター」という見出しが表示されてます。
日付、発表者、研究会名など - その1
「研究会名」といったHTML既定の印(タグ)はないので、印の工夫から始めます。
Vivliostyle用のMarkdownとして開発されている、VFM (Vivliostyle Flavored Markdown13)は、Markdownの見出しに応じてsection
要素を生成して階層化してくれます14。これを利用します。
印を付ける
Markdown (VFM)で「研究会名」という見出しにconference
クラスを設定します:
### 研究会名{.conference}
第3回 プレゼン研究発表会
すると、次のようなHTMLが生成されます:
<section class="level3" aria-labelledby="研究会名">
<h3 class="conference" id="研究会名">研究会名</h3>
<p>第3回 プレゼン研究発表会</p>
</section>
これで"第3回 プレゼン研究発表会"
に印が付きました。つまり、:has(> .conference) > p
というセレクターで取り出せます。「印が付く」=「セレクターで選べる」です。
名前を付ける
ここで次のようなCSSを適用すると、"第3回 プレゼン研究発表会"
にstring-conference
という名前が付きます。
h2.conference {
display: none;
}
:has(> .conference) > p {
string-set: string-conference content();
}
「研究会名」という見出しそのものはスライドに表示しないのでdisplay: none;
としています。
フッターに生成する
次の設定で@bottom-center
マージンに研究会名を表示します。
@page {
@bottom-center { content: string(string-conference); }
}
スライドの下中央に「第3回 プレゼン研究発表会」と表示されました。
日付、発表者、研究会名など - その2
「研究会名」を識別する印(タグ)を前提としないような、印の工夫から始めます。
印を付ける
VFMで次のように書いて、@bottom-center
マージンに表示したい項目にbottom-center
クラスを設定すると、次のようなHTMLが生成されます(aria-labelledby
属性などを省略してます):
### 研究会名{.conference .bottom-center}
第3回 プレゼン研究発表会
<section>
<h3 class="conference bottom-center">研究会名</h3>
<p>第3回 プレゼン研究発表会</p>
</section>
"第3回 プレゼン研究発表会"
に印が付きました。:has(> .bottom-center) > p
というセレクターで取り出せます。
名前を付ける
ここで次のようなCSSを適用すると、"第3回 プレゼン研究発表会"
にstring-bottom-center
という名前が付きます。
:has(> .bottom-center) > p:first-of-type {
string-set: string-bottom-center content();
}
フッターに生成する
@bottom-center
マージンに表示します。
@page {
@bottom-center { content: string(string-bottom-center); }
}
スライドの下中央に「第3回 プレゼン研究発表会」と表示されました。
日付、発表者、研究会名など - 検討
日付、発表者、研究会名などを本文から抜き出してヘッダー/フッターに表示する方法について、少し振り返ってみます。
印と見出し
印を付けるために見出し##
や###
に.conference
クラスを設定して利用しました。
- 印に見出しを利用すると、Markdownエディターのアウトライン表示に印が表示されます
- このことを覚えておいて、後で説明するスライド区切りの設定などに必ず反映します
Markdownエディターでのアウトライン表示にこだわらなければ、その1方式のMarkdownで次のように書いて印を付けられます。
これは<span class="conference">プレゼン学会 第4回研究発表会</span>で発表したものです。
方式の比較
その1方式とその2方式、どちらがよいかは意見が分かれるところでしょう。
その1方式
- Markdownを見ただけでは、フッター中央に何が表示されるか分かりません。何を表示するかはCSS側で決めます。
- CSSには
.conference
(を直下に持つsection
の最初のp
)をフッター中央に表示すると書いてあります。.conference
はMarkdown(というかHTML)側が決めた印(クラス)ですが、CSS側はこれを前提にしています。 - このCSSをたまたま見つけてスタイルを気に入った発表者が、発表者名をフッター中央に表示したいと思ったら、発表者名に
.conference
クラスを設定するでしょう。
その2方式
- CSSを見ただけでは、フッター中央に何が表示されるか分かりません。何を表示するかはMarkdown側で
.bottom-center
クラスを指定して決めます。 - これはMarkdown側にスタイル情報を含めることを意味します。
スライド番号 / 総スライド数
各スライドに番号(ページ番号)があると、Q&Aタイムで各スライドにランダムアクセスしやすいです。また、総スライド数が表示されていると、発表者本人だけでなく座長や聴いてる人たちも安心です。
スライド番号(ページ番号)や総スライド数(総ページ数)は、何もしなくても、それぞれpage
とpages
カウンターに設定されています。
そこで、CSSに次のように書くだけで、右下マージンに「スライド番号 / 総スライド数」が表示されます。
@page {
@bottom-right {
content: counter(page) " / " counter(pages);
}
}
スライドの右下に「10 / 24」と表示されました。10番目のスライドで、総スライド数が24です。
参考文献を脚注や文末脚注として表示
研究発表会のプレゼンでは、主な参考文献を脚注として各スライドの下部に表示(脚注)したり、最後のスライドにまとめて表示(文末脚注)したりすることがあります。
各スライドの下部に表示する例
サンプルのCSSでは、スライド下部に脚注として表示する場合は、span
要素を使ってfn
クラスを設定します。
…VFM (Vivliostyle Flavored Markdown)<span class="fn">[Vivliostyleに特化したMarkdown - VFMの使い方](https://gihyo.jp/article/2024/03/vivliostyle-02)</span>は、Markdownの見出しに応じてsection要素を生成して
「VFM (Vivliostyle Flavored Markdown)」の右肩に「*4」が付いて、そのスライド下部に本体が脚注として表示されました。
最後のスライドにまとめて表示する例
最後のスライドにまとめて表示する場合は、Markdownの記法はQiitaと同じです。
…ちなみに、CSS (Cascading Style Sheets)でも脚注を実現できます[^CSS]。
[^CSS]: CSS Generated Content for Paged Media Module 2. Footnotes [https://www.w3.org/TR/css-gcpm-3/#footnotes](https://www.w3.org/TR/css-gcpm-3/#footnotes)
注の本体は最後のスライドにまとめて表示されます。
スライドに詰め込む
(was:文字サイズの調整)
「1行だけスライドから溢れてしまったけど、テキストを修正する余裕がない」ことってありますよね。
見出しより下の部分を<div style="font-size: 90%;">…</div>
で囲んで文字サイズを調整します。
下のMarkdownが次のようだとすると:
## 見出し
このスライドの文字を小さくしたい。
次のように見出しより下の部分を囲みます:
## 見出し
<div style="font-size: 60%;">
このスライドの文字を小さくしたい。
</div>
その他の方法
他の方法で調整できるかもしれません。前の例のfont-size: 70%;
部分には、次のようなパターンが考えら得ます。ただし、読みにくくなって不評を買うかもしれません。
-
font-size: 90%;
などで文字のサイズを少し小さくしてみます -
line-height: 1;
などで行の幅を指定します。1
などの数字にフォントサイズを掛けたものなります。1.5
や1.8
になってることが多いので、少し狭くしてみます -
word-break: break-all;
で禁則なども無視して改行できるようにします。word-break: auto-phrase;
は行数が増えがちです -
margin-inline-start: -2em;
、margin-inline-end: -2em;
などで文字が進む方向の余白(マージン)の大きさを負にすると、行頭(-start
)や行末(-end
)で使える幅が広がって長い行が収まります -
margin-block-start: -1em;
やmargin-block-end: -1em;
などで行が進む方向の余白の大きさを負にすると、収まる行数が増えます…が、前後の行の文字と重なるかもしれません -
letter-spacing: -1px;
などで字間のスペースに負の値を指定します -
position: relative; left: -1em; top: -1em;
などとすると、サイズではなく位置(position)を上下左右にズラせます。この例だと左(left)に1文字分、上(top)に1文字分ズレ(relative)ます
スライドとしての基本的なスタイル設定とプレゼン操作
「A4の論文の印刷」ではなく「プレゼンのスライド」であるために、以下のようなお膳立てをします。
用紙サイズをA5横くらいに設定
A5横を基本に4:3や16:9になるように調整すると、見出しなどの既定の文字サイズがほどよい大きさになるでしょう9。
@page {
size: A5 landscape; /* 210mm 148mm */
/* size: 216mm 162mm; 4:3 */
/* size: 256mm 144mm; 16:9 */
}
##
と###
でスライドを区切る
break-before
プロパティ15を使って、##
(HTMLのh2
)に加えて###
(HTMLのh3
)くらいまでを既定のスライド区切りにしておきます。
- VFMの場合、それらを直下に持つ
section
要素を1枚のスライドに対応させます - ヘッダー/フッターに表示するため導入した
.conference
クラスなど、便利な印を設定したh2
やh3
をスライド区切りから除外します
任意でスライドを区切るためにの.break-before-page
クラスと、スライド区切りを止める.break-before-auto
といったクラスも用意しておくと便利です。
.break-before-page,
section:has(> h2),
section:has(> h3:not(.conference, .bottom-center)) {
break-before: page;
}
.break-before-auto,
section:has(> h2.break-before-auto, > h3.break-before-auto) {
break-before: auto;
}
アウトライン番号
見出しの前に「1.」、「1.1」などと番号を振って、アウトライン(section
構造)を示すと、プレゼンのときに今どこの話をしてるのか、聞き手が理解する助けになります。プレゼン・アプリには見られない機能です。
プレゼンはVivliostyleやPDFで
Vivliostyle Viewerではズーム(拡大/縮小)したり文字サイズを変更したりハイライトしたりできます
- ズームではスライド全体が拡大・縮小します
- 文字サイズの変更では、そのサイズで再レイアウトされ、スライド数が増えたり減ったりすることがあります
- ちなみに画像は、文字サイズに基づいて
block-size: 2em;
などと指定していると、文字とあわせて一緒にサイズが変わります。block-size: 320px;
などの指定では、サイズは変わりません
もちろん、PDFで保存してPDFでプレゼンすることもできます。
レイアウトのテンプレート
最後に少しだけ…
CSSで、本文のテキストを2次元に配置したりできます。
次のようなMarkdownのテキストを:
### ポイント1
- こういった配置は他の誰かがデザインしたものを使えるとよいですね。
- この話は別の機会に
### ポイント2
- CSSの競合/相互作用を制御する**お約束**が必要でしょう。
- みんなが`!important`を使う世界もどうかと思いますし。
### ポイント3
- 色は匂へど散りぬるを
- 我が世誰ぞ常ならむ
- 有為の奥山今日越えて
- 浅き夢見し酔ひもせず。
### ポイント4
- 色は匂へど散りぬるを
- 我が世誰ぞ常ならむ
- 有為の奥山今日越えて
- 浅き夢見し酔ひもせず。
次のスライドの、「9.1 表示」の下のように表示できます:
こういった配置は色や背景も含めていろんなパターンが考えられます。しかし、ゼミのレビューや発表当日が迫るなか、そんなCSSをゼロから工夫するのは苦しいです。
そこで、いろんなパターンがテンプレートなどとしてあらかじめ用意されてるとよいですね。それは複数の人が作ったCSSを組み合わせて使う世界なので、何らかのお約束が必要でしょう。この例のCSSは、このスライドのための個別CSSに設定してあって、テーマCSSで設定された見出し###
の番号生成や改スライドを無効にするなどの工夫が必要でした。
サンプルを試す
Vivliostyleでサンプルを試す方法です
Vivliostyleのインストール方法はこちらの記事にあります:
実際に使ってみよう - Vivliostyleでなにができるの?
サンプルのMarkdown、図、CSSをダウンロードして、次のファイル構造にしてください(図はなくても、とりあえずエラーにはなりません):
|--author.css
|--figure
| |--arrow-down.svg
| |--arrow-right.svg
| |--circle.svg
| |--figure.svg
| |--highlight.png
|--slide.md
|--theme.css
ここで次のコマンドを実行するとスライドをプレビューできます:
$ vivliostyle preview slide.md -T theme.css
ウィンドウを閉じるとプレビューが修了します。
PDFを出力するには次のようにします:
$ vivliostyle build slide.md -o slide.pdf -T theme.css
-T
または--theme
オプションはスライドのCSSファイルを指定します。-o
または--output
オプションは出力のファイルです。
author.css
もCSSファイルですが、これを使うことはslide.md
ファイルの中の次の記述で指定しています:
---
link:
- rel: 'stylesheet'
href: 'author.css'
---
theme.css
はみんなのスライドで使えるように用意したCSSで、Vivliostyleではテーマ(theme)と呼びます。Vivliostyle Theme16というと、このようなテーマCSSやテーマCSSを運用する仕組みを指します。
author.css
はこのサンプルのスライド用に用意したCSSです。矢印や2次元配置は、ここで定義しています。
-
Vivliostyle https://vivliostyle.org/ ↩
-
Vivliostyleが拓くCSS組版の可能性 記事一覧 https://gihyo.jp/list/group/Vivliostyle%E3%81%8C%E6%8B%93%E3%81%8FCSS%E7%B5%84%E7%89%88%E3%81%AE%E5%8F%AF%E8%83%BD%E6%80%A7 ↩
-
3.1. The float-reference property - CSS Page Floats https://drafts.csswg.org/css-page-floats/#float-reference-property ↩
-
3.2. The float property - CSS Page Floats https://drafts.csswg.org/css-page-floats/#float-property ↩
-
word-break https://developer.mozilla.org/ja/docs/Web/CSS/word-break ↩
-
text-wrap https://developer.mozilla.org/ja/docs/Web/CSS/text-wrap ↩
-
text-spacing-trim https://developer.mozilla.org/ja/docs/Web/CSS/text-spacing-trim ↩
-
CSS - text-spacing-trim - とほほのWWW入門 https://www.tohoho-web.com/css/prop/text-spacing-trim.htm ↩
-
@page https://developer.mozilla.org/ja/docs/Web/CSS/@page ↩ ↩2
-
CSS Paged Media Module Level 3 - 5. Page-Margin Boxes https://www.w3.org/TR/css-page-3/#margin-boxes ↩
-
CSS - @page - とほほのWWW入門 https://www.tohoho-web.com/css/rule/page.htm ↩
-
1.1. Named strings - CSS Generated Content for Paged Media Module https://www.w3.org/TR/css-gcpm-3/#named-strings ↩
-
break-before https://developer.mozilla.org/ja/docs/Web/CSS/break-before ↩