Beamer columns 環境で画像を配置するベストな方法

この記事では，LaTeX Beamer で画像をいい感じの位置に置く方法，特に `columns` 環境を使う方法を扱います．

## §.0. ことの始まり

後輩氏「Beamer で画像挿入うまくいかないんやで．[コレ](http://qiita.com/t_uda/items/e9ea53fab43845129d8b)見てやってみたんやで．」
私氏「誰やこんな**クソみたいなコード**書いたやつは．あ，**私やんけ**．」
Google氏「『Beamer 画像』で上の方に出しといてあげたやで．」
私氏「マジかよ勘弁しちくり〜〜〜」

そういうわけで，3 年前のアレなコード[^0]に引導を渡すべく，Beamer で画像を意図通り配置するための**本当のベストプラクティス**について考察していきたいと思います．

[^0]: 元を辿れば私が 2004 年の資料からろくに考えずにオマジナイをサルベージしてしまったことが発端ですから，そういう意味では 10 年モノのアレコードですね:(

## §.1. はじめに

本稿のサンプルは，執筆時にいくつかの環境 (TeX Live 2015 / Mac OS X, TeX Live 2014 / Debian Jessie, etc.) にてタイプセットできることを確認しています．以下に，サンプル用のコマンド定義を含むプリアンブルを示します．

```latex:beamer-column.tex
\PassOptionsToClass{hiresbb}{graphicx}
\documentclass[dvipdfmx]{beamer}
\usepackage{graphicx}
\newcommand{\thickhrulefill}{\leavevmode\leaders\hrule depth-1.2pt height 3.2pt\hfill\kern0pt}
\newcommand{\indicatewidth}[1]{\thickhrulefill{#1}\thickhrulefill}
\begin{document}
...
\end{document}
```

上のサンプルは `platex + dvipdfmx` を前提としていますが，本稿の内容は `pdflatex` 等の場合でも全く同様です（オプションのドライバ等は適宜書き換えてください）．本稿には，スクリーンショット以外には必要最小限のコードしか載せていません．スクリーンショットを再現するためのサンプルコード全文は [Gist](https://gist.github.com/t-uda/65e25b220a63e5e2e5c4) を参照してください．

画像の挿入に関する一般的なトラブルシューティングに関しては本稿では扱っていません（何かお困りの場合はまず[日本人のための LaTeX タブー集 ～画像読込編～](http://qiita.com/zr_tex8r/items/5413a29d5276acac3771)を読むことを強くお薦めします）．

## §.2. オマジナイに頼ってはいけない

3 年前の記事「[Beamer 2-column スライドで片方に画像を表示](http://qiita.com/t_uda/items/e9ea53fab43845129d8b)」で掲載したイディオムは，以下に挙げる理由により**使ってはいけません**．

* 一度はうまく行くように見えますが，このイディオム二度使用すると，意図通りに表示されなくなります．
    * 特に，Beamer theme の他の要素に破壊的な影響を与える可能性があり，たいへん危険といえます．
* `\pgfputat` および `\pgfxy` は古いバージョンとの互換性のために残されている命令ですので，標準で定義されているとは限りません．
    * `\usepackage{pgf}` すれば互換性のための命令も一応は定義されます[^1]．
    * 最新のマニュアル "TikZ & PGF Manual for Version 3.0.1a" にもこれらの命令に関する記述はありません (Cf. `texdoc pgf`)．Undocumented な命令に頼るべきではありません．

[^1]: Beamer は PGF に依存していますが，基本的にはコアパッケージ `pgfcore.sty` しか読み込みません．ですので，後方互換性のための命令は未定義となります．どうしてもこれらの命令を使いたい場合は，`pgf.sty` もしくはピンポイントで `pgfcomp-version-0-65.sty` を読み込めば使えるようになります．

## §.3. `columns` 環境の正しい使い方

Beamer で画像を配置する方法で困ったときに，最初に考慮すべき方法は `columns` 環境を使うことです．`columns` は由緒正しい (?) Beamer の環境であり，Beamer マニュアルにも

> Usually, place graphics to the left of the text. (Use the **columns** environment.) In a left-to-right reading culture, we look at the left first.

と書かれています[^2]（強調は筆者）．しかし，この方法は公式推奨の癖に割と罠だらけです（ある意味前述の方法もそうですが）．実は，`columns` 環境を使って画像を思い通りの位置に置けないとき，その原因は画像のほうではなく `columns` 環境のほうにあることが多いです[^3]．ということでまずは `columns` 環境について詳しくみていきます．

[^2]: 個人的には画像は右に置きたい派なのでこの文章はちょっとだけ気に食わないですけどね．まぁ文化や分野の違いもあるのかもしません．
[^3]: PGF イディオムのほうがうまくいかないのは `columns` 環境のせいではありませんよ:)

### `column(s)` 環境の width の指定について
次の例をみてください．

```latex
\begin{frame}
  \begin{block}{columns[t], 0.5:0.5}
    \fbox{
    \begin{columns}[t]
      \begin{column}{0.5\linewidth}\indicatewidth{left column}\end{column}
      \begin{column}{0.5\linewidth}\indicatewidth{right column}\end{column}
    \end{columns}
    }
    \par\indicatewidth{outside}
  \end{block}
\end{frame}
```

`\indicatewidth{}` は上でサンプル用に定義した，幅めいっぱいに「横線」を引く命令です．これをタイプセットすると図のようになります．地の文の行幅に対して `columns` の幅が広く，またそれぞれの `column` がちょっと外側にはみ出ている様子が分かります．

![スクリーンショット 2016-02-13 21.27.00.png](https://qiita-image-store.s3.amazonaws.com/0/2251/79be37b7-dccb-f0b3-2d2e-b2dbb8720a41.png)

そこで `[onlytextwidth]` オプションを指定したところが次の図です．このオプションは `[totalwidth=\textwidth]` と同じ効果をもち，columns 領域幅をちょうど一行分だけとるということです．中に収まりましたが今度は中央がくっつきました．

![スクリーンショット 2016-02-13 21.27.51.png](https://qiita-image-store.s3.amazonaws.com/0/2251/6cce27ff-10fb-9b88-1339-78c6f0fb470b.png)

中央がくっついているのは，幅の合計が 1 にならないようにすると解消されます．`columns` 環境はマージンのことまでよしなにはしてくれませんから，合計をぴったり 1 にするよりも，適当にバッファを持たせる方が見た目よく振舞うことが多いです．右側余白が小さい問題も，`totalwidth` を適当に 1 より小さい幅を指定するのが簡単です（やはりマージンのことまでよしなにはしてくれません）．

![スクリーンショット 2016-02-13 21.28.48.png](https://qiita-image-store.s3.amazonaws.com/0/2251/f35af04b-b7a7-6097-fa6b-ffd96be74333.png)

まとめると，`columns` の `totalwidth` および各 `column` の幅は，ぴったりの値より小さめに設定するのが良いです．

参考に，3 段組の場合も掲載しておきます．

![スクリーンショット 2016-02-13 21.31.01.png](https://qiita-image-store.s3.amazonaws.com/0/2251/2b404727-b7c5-a86d-ec37-69c3b898b3a4.png)

### `\includegraphics` とアラインメント

さて，画像の話に移ります．実は，`\includegraphics` と組み合わせると，また新たな問題が発生します．次のコードとそのタイプセット結果をみてください．

```latex
\begin{frame}{悪い例}
  \begin{block}{[t], 0.8:0.2}
    \fbox{
    \begin{columns}[t]
      \begin{column}{0.8\linewidth}
        some paragraph\par some paragraph
        \par\indicatewidth{left}
      \end{column}
      \begin{column}{0.2\linewidth}
        \fbox{\includegraphics[width=1.0\linewidth]{pic/0inN.png}}
        \par\indicatewidth{right}
      \end{column}
    \end{columns}
    }
  \end{block}
\end{frame}
```

![スクリーンショット 2016-02-13 21.32.41.png](https://qiita-image-store.s3.amazonaws.com/0/2251/f9538a27-02ae-55b8-185e-37727f14f87f.png)

あらまーひどい！ まぁちょっと考えれば分かることなんですが，これはアラインメントオプション `[t]` によるものです（さっきから明示的に指定していましたがこれは `columns` 環境のデフォルトです）．`[t]` は各カラムの**一行目のベースラインを上揃え**するものですから，各カラムの最初の行の高さが違えばこのとおり！

![スクリーンショット 2016-02-13 21.34.02.png](https://qiita-image-store.s3.amazonaws.com/0/2251/6f9605df-d902-4216-496e-f0479db3a1a5.png)

`columns` の幅指定に余裕をもたせて，横にはみ出る問題も解消してあります．この上揃いが `\includegraphics` と `columns` を組み合わせたときの不細工なレイアウトの正体です．したがって，アラインメントオプションを適切に指定することで解消できます．それぞれのオプションの意味は以下のとおりです．

* `[t]`: 上揃え（一行目ベースライン）
* `[T]`: 上揃え（一行目上端）
* `[c]`: 中央揃え
* `[b]`: 下揃え

![スクリーンショット 2016-02-13 21.35.49.png](https://qiita-image-store.s3.amazonaws.com/0/2251/4f18c8ac-81fd-726c-4e39-596e44b2caa1.png)

`[T]` を使うことでベースラインではなく上端基準で揃えられるので，画像を組み合わせる場合はこのオプションを使うといいでしょう[^5]．また，`columns` ではなく個別の `column` にアラインメントを指定することで，途中でアラインメントを変更することもできます．上の `[T]` の例では，文章・画像ともに少し上にはみ出ていますが，`[t]` と `[T]` を使い分けることでいい感じになります．

[^5]: > T is similar to the t option, but T aligns the tops of the first lines while t aligns the so-called baselines of the first lines. If strange things seem to happen in conjunction with the t option (for example if a graphic suddenly “drops down” with the t option instead of “going up,”), try using this option instead. (Cf. `texdoc beamer`)

![スクリーンショット 2016-02-13 21.36.52.png](https://qiita-image-store.s3.amazonaws.com/0/2251/85ceb9b7-abfd-fb1c-62c9-f6ae97901462.png)

左の column には `[t]` を，右の column には `[T]` を，それぞれ指定しています．ただし，場合によると思いますが，`[c]` や `[b]` とは組み合わせない方がいいでしょう．

### `figure` 環境も使う場合

`figure` 環境を使いたい人もいると思うので，一応言及しておきます．まずは例によって悪い例から．

```latex
\begin{frame}{figure環境を使った悪い例}
  \begin{block}{[t], 0.8:0.2, figure}
    \fbox{
    \begin{columns}[t]
      \begin{column}{0.8\linewidth}
        some paragraph\par some paragraph
        \par\indicatewidth{left}
      \end{column}
      \begin{column}{0.2\linewidth}
        \begin{figure}
          \fbox{\includegraphics[width=1.0\linewidth]{pic/0inN.png}}
        \end{figure}
        \par\indicatewidth{right}
      \end{column}
    \end{columns}
    }
  \end{block}
\end{frame}
```

![スクリーンショット 2016-02-13 21.39.54.png](https://qiita-image-store.s3.amazonaws.com/0/2251/8bea88cd-5ca7-9994-6fed-eb1303f3d57c.png)

あ，ハイ，今度はそうなるんですね．

分かりづらいですが，`figure` 環境の作る余白の分だけ下がって上揃えされています．そもそも Beamer での `figure` は floating box ではなくただ `center` 環境をラップしたものです．この空白が嫌であれば，`figure` 環境ではなく `\centering` を使うべきです．`\caption` をつけたいなどの理由があってかつどうしても上に詰めたければ，段落一行分くらいのネガティブスペースを入れるしかないでしょう．

![スクリーンショット 2016-02-13 21.41.07.png](https://qiita-image-store.s3.amazonaws.com/0/2251/2799977f-2f92-f70b-421e-b0d831dff6de.png)

### [こらむ]: `\ナントカwidth` の違い

結論を言うと，`\ナントカwidth` の違いはあまりありません．

幅の長さを表す命令として `\hsize`, `\textwidth`, `\columnwidth`, `\linewidth` などがありますが，いずれも `column(s)` 環境の幅を指定する際には同じ値を持つハズです．したがって，どれを使っても差し支えありません．ちなみに `\columnwidth` は文書の段組 (e.g. `\documentclass[twocolumn]{article}`) に応じた値をもつものであり，`column(s)` 環境とは直接関係ありません．よって `\columnwidth` を使って幅を指定するのは混乱の元ですから，やめたほうがいいでしょう．

一応，他に違いが出る状況として，`itemize` 内で `columns` を用いたときなどが考えられますが，まぁナイでしょう．詳しいことはこちら [Difference between \textwidth, \linewidth and \hsize](http://tex.stackexchange.com/questions/16942/difference-between-textwidth-linewidth-and-hsize) の質問への回答が参考になります．

**2016-03-01追記**: 上の書き方だと，さも `\columnwidth` の値はその文書内で不変であるかのように読め，そのため `columns` 環境をネストしているとき（あるいはより一般に `minipage` 環境にいるときなど）には違いが出るんじゃないかと思われそうですが，実際にはその場合ですら同じ値を持ちます．つまり，`minipage` は常に一段組みであり結局のところ `\textwidth` と `\columnwidth` は同じ値になります．ちなみに二段組み文書のトップレベルならばちゃんと `\textwidth` が `\columnwidth` の約 2 倍の値を持ちます．

## §.4. 最後の手段

一応，最終手段として，絶対座標指定して好きな位置に置く方法があります．それはもう割と面倒ですし，本稿の趣旨からは外れてしまいますので，Beamer マニュアルの文章を引用するにとどめます．

> ### 12.8 Positioning Text and Graphics Absolutely
> Normally, beamer uses TeX's normal typesetting mechanism to position text and graphics on the page. In certain situation you may instead wish a certain text or graphic to appear at a page position that is specified absolutely. This means that the position is specified relative to the upper left corner of the slide.
> The package **textpos** provides several commands for positioning text absolutely and it works together with beamer. When using this package, you will typically have to specify the options overlay and perhaps absolute. For details on how to use the package, please see its documentation.

（Cf. `texdoc beamer`; 強調は筆者）

意訳：`texdoc textpos` とかを読んでね．

あと `wrapfig` を使う方法もありますが，この方法はあまり Beamer 向きではないように私は思います（これも色々落とし穴だらけだし）．

## §.5. ベストプラクティス

以上のことを踏まえた二段組みサンプルです．**チョット余裕を持たせる**のがそれはそれは面倒ですので，`\mytotalwidth` と `\mycolumnwidth` を新たに定義しています（`5mm` ではなくそれらしいマージンの値を引っ張ってくる方がいいかもしれません）．

```latex:best-practice.tex
\newlength{\mytotalwidth}
\mytotalwidth=\dimexpr\linewidth-5mm
\newlength{\mycolumnwidth}
\mycolumnwidth=\dimexpr\mytotalwidth-5mm

\begin{frame}
  \begin{block}{[totalwidth=\textbackslash{}mytotalwidth], [t]+[T], 0.5:0.5}
    \fbox{
    \begin{columns}[totalwidth=\mytotalwidth]
      \begin{column}[t]{0.5\mycolumnwidth}
        \indicatewidth{left}
      \end{column}
      \begin{column}[T]{0.5\mycolumnwidth}
        \centering
        \fbox{\includegraphics[width=20pt]{pic/0inN.png}}
        \par\indicatewidth{right}
      \end{column}
    \end{columns}
    }
    \par\indicatewidth{outside}
  \end{block}
\end{frame}
```

![スクリーンショット 2016-02-13 21.41.44.png](https://qiita-image-store.s3.amazonaws.com/0/2251/58fca714-a1ef-97d5-473c-8c29c3348b6c.png)

もちろんこれは上揃えしたい場合の例であって，中央揃えの方が見栄え良い場合も多いでしょう．

## まとめ

* PGF の `\pgfputat`, `\pgfxy` によるオマジナイは使ってはいけません．
* `columns` および `column` の幅は，余裕をもたせた値を指定しましょう．
* 画像を上に揃えたいときは，`[t]` と `[T]` オプションを組み合わせましょう．
* 最終手段として，絶対座標指定もできます．

3 年前の二の舞にならないためにも，TeXnitian の皆様からの御指摘，御指南，そしてより良いご提案をお待ちしています．

----