5.8 多段組み (*)
Pandoc の Markdown はスライド文書に対する多段レイアウトをサポートしていますが, 他のタイプの文書ではサポートしていません. このレシピでは通常の HTML 文書や LaTeX 文書での多段レイアウトを使う方法を紹介します22. これは knitr の issue https://github.com/yihui/knitr/issues/1743 での Atsushi Yasumoto23 の解決策に着想を得ました.
考慮する必要があるのが HTML 出力のみなら話はかなり単純です. 任意の HTML 要素を横に並べて表示するのはCSS を使えば比較的簡単にできるからです. コードチャンクのテキスト出力を横に並べるだけならば, もっと簡単になります. 以下は1つ目の例です.
---
output: html_document
---
```{r attr.source="style='display:inline-block;'", collapse=TRUE}
1:10 # 1 から 10 の数列
10:1 # その逆順
```
CSS 属性 display: inline-block;
は, コードブロックの出力 (つまり HTML タグの <pre>
です) をインライン要素として表示しなさいという意味です. デフォルトではこれらのブロックはブロックレベル要素 (つまり display: block;
) として表示され, 行を丸ごと占有します. チャンクオプション collapse = TRUE
はテキスト出力を R ソースコードブロックと結合することを意味するので, ソースとテキスト出力が同じ <pre>
ブロックに配置されます.
HTML 出力時に任意の順で横に並べたい場合, Pandoc の fenced Div
. を使うことができます. “Div” は HTML タグの <div>
に由来しますが, 任意のブロックやコンテナと解釈できます. Div
の開始と終了は は3つ以上のコロン (例: :::
) です. より多くのコロンの Div
は, よりコロンの少ない Div
を含むことができます. fenced Div
の重要で有用な機能は, これに属性を付与できるということです. 例えば CSS 属性 display: flex;
を外側のコンテナに適用できるので, 内側のコンテナは横並びに配置されます.
---
output: html_document
---
:::: {style="display: flex;"}
::: {}
ここは **最初の** Div です.
```{r}
str(iris)
```
:::
::: {}
こっちは右側に配置されるブロックです.
```{r}
plot(iris[, -5])
```
:::
::::
上記の例では外側の Div
(::::
) は2つの Div
(:::
) を含んでいます. この中にさらに Div
を追加することもできます. とても強力な CSS 属性 display: flex;
(CSS Flexbox) についてもっと知るためには https://css-tricks.com/snippets/css/a-guide-to-flexbox/ というガイドを読めばよいでしょう. CSS グリッド (display: grid;
) もまた強力で, 上記の例にも使えます. もし試してみたいなら, display: flex;
を display: grid; grid-template-columns: 1fr 1fr; grid-column-gap: 10px;
に置き換えてみてください. グリッドレイアウトについてもっと知りたければ, https://css-tricks.com/snippets/css/complete-guide-grid/ のガイドを見てください.
HTML でも LaTeX でも同じように使えるレイアウトにしたいのなら, よりトリッキーになります. 以下に HTML, LaTeX そして Beamer で使える用例の全容を示します.
---
output:
pdf_document:
latex_engine: lualatex
keep_tex: true
includes:
in_header: columns.tex
html_document:
css: columns.css
beamer_presentation:
keep_tex: true
latex_engine: lualatex
includes:
in_header: columns.tex
documentclass: "`r if(knitr::opts_knit$get('rmarkdown.pandoc.to') == 'beamer') 'beamer' else 'ltjsarticle'`"
mainfont: 'Noto Sans CJK JP'
---
# 二段組み
以下は 3つの子要素の Div を横並びに持つ Div コンテナです. 中央の Div は空で, 左右の Div の間に空白を作るためだけに存在します.
:::::: {.cols data-latex=""}
::: {.col data-latex="{0.55\textwidth}"}```{r, echo=FALSE, fig.width=5, fig.height=4}
par(mar = c(4, 4, .2, .1))
plot(cars, pch = 19)
```
:::
::: {.col data-latex="{0.05\textwidth}"}
\ <!-- 段どうしのセパレータとして機能するだけの空の Div (空白入り) -->
:::
::: {.col data-latex="{0.4\textwidth}"}`cars` データを表しています.
左側の図は
> いろはにほへと ちりぬるを
わかよたれそ つねならむ
うゐのおくやま けふこえて
あさきゆめみし ゑひもせす
::: ::::::
図5.3 がその出力です. この例では外側の .cols
クラスを持つ Div
と, 内側に .col
クラスを持つ3つの Div
を使っています. HTML 出力では, 外部 CSS ファイル columns.css
を導入し, その中で Flexbox レイアウトを外側の Div
に適用しているので, 内側の Div
が横並びになります.
.cols {display: flex; }
LaTeX 出力 (pdf_document
) では, columns.tex
に含まれている「あまり行儀の良くない裏ワザ」をLaTeX プリアンブルに適用し, LaTeX 環境 cols
と col
を定義しなければなりません.
\newenvironment{cols}[1][]{}{}
\newenvironment{col}[1]{\begin{minipage}{#1}\ignorespaces}{%
\end{minipage}
\ifhmode\unskip\fi
\aftergroup\useignorespacesandallpars}
\def\useignorespacesandallpars#1\ignorespaces\fi{%
\fi\ignorespacesandallpars}
#1
\makeatletter
\def\ignorespacesandallpars{%
\@ifnextchar\par
\expandafter\ignorespacesandallpars\@gobble}%
{%
{}
}\makeatother
col
環境が特に複雑な主な理由としては, LaTeX 出力で Pandoc は各 Div
でいつも段落を改めるので, この改段を除去しなければならないからです. そうしないと Div
を横並びに配置することはできません. このハックは https://tex.stackexchange.com/q/179016/9128 から借用しました.
Beamer 出力でも columns.tex
で同じハックを適用しています. Pandoc は スライドショー用に ::: {.columns}
, ::: {.column}
, ::: {.incremental}
といった特別な Div
を提供していることに注意してください. これらは特別な意味を持つため, この節のような方法で Div
を LaTeX 環境に変換するときには, これらのタイプの Div
を使わないように注意しなければなりません. columns
や column
という名前の Div
タイプを使わず, cols
, col
使ったのは, これが理由です.
fenced Div
についてより詳しく知りたいなら, 9.6節を見てください.