キャプションとサブ図

図の番号がひとつもずれていないのに \ref だけが違う番号を返す——LaTeX でもっとも報告の多い「間違った図番号」は、たいてい \label\caption に書いたことが原因です。エラーも警告も出ず、印刷された数字だけが静かに嘘をつきます。キャプションは見た目こそ地味ですが、番号付け・相互参照・図表目次の三つがすべてここで決まる要の命令です。このページでは \caption がフロートの中でしか動かない理由、\label を置く位置、caption パッケージによる体裁の調整、フロートの外で使う \captionof、そして (a)(b) に分けるサブ図を扱います。

\caption はフロートの中でしか動かない

\caption{…} は図表に説明文を添える命令ですが、figuretable の内側でしか使えません。地の文にそのまま書くと ! LaTeX Error: \caption outside float. で止まります。理由は、この命令が単に文字を組んでいるのではなく、「いま自分はどの種類のフロートの中にいるか」を見て対応するカウンタを進めている からです。figure の中なら figure カウンタを、table の中なら table カウンタを進める。フロートの外にはその情報がないので、番号の付けようがありません。だから番号を自分で書く必要はまったくなく、書いてはいけません。

latex
\begin{figure}
  \centering
  \includegraphics[width=0.6\textwidth]{plot}
  \caption{Measured values against the theoretical curve}
  \label{fig:plot}   % after \caption -- always
\end{figure}

配置の慣習にも触れておきます。図のキャプションは図の下、表のキャプションは表の上 に置くのが一般的です。表は上から下へ読むので、何の表かを先に告げるほうが自然だからです。LaTeX は \caption を書いた位置にそのまま組むので、上に出したければ図版より前に、下に出したければ後に書きます。番号と本文の間隔などの体裁自体は位置によって変わりません。ただしこの向きは投稿先の規定で決まっていることが多いので、まずは学会誌のスタイルガイドを確認してください。

\label\caption の前に書くと何が起きるか

\label は必ず \caption の後ろに置きます。 \label は「いまの番号」を記録するだけの命令で、その「いまの番号」を図の番号に更新するのは \caption です。だから \caption より前に \label を書くと、直前に動いたカウンタ——ふつうは節番号——がそのまま記録されます。実際に第 5 節の中で、番号 2 になるはずの図に \caption より前の \label を付けて組むと、補助ファイルには \newlabel{fig:before}{{5}{1}...} と書かれ、本文には「図 5」と印字されます。エラーも警告も一切出ません。 出力を目で確かめない限り、この間違いは最後まで見つかりません。

この罠には型があります。\includegraphics の直後に \label を書きたくなるのが人情——画像に名札を付けている気分になるからです。しかし LaTeX にとって \label が指しているのは画像ではなく カウンタ であり、そのカウンタを設定するのは \caption です。対策は単純で、\caption\label を必ず隣り合った 2 行にする。あいだに何も挟まなければ、順序を間違えようがありません。サブ図でも同じで、subfigure 環境の中の \label はその中の \caption の後ろに置きます。\ref\label の一般的な仕組みは、相互参照のページが詳しく扱っています。

短い見出しと図目次 — \caption[...]{...}\caption*\ContinuedFloat

キャプションが長く、図目次には一行だけ載せたい——そのための任意引数が \caption[短い見出し]{長い本文} です。角括弧の中が \listoffigures の一覧に、波括弧の中が図のそばに 組まれます。角括弧を省くと本文がそのまま一覧にも流れ込むので、三行のキャプションを持つ図が並ぶと目次が壊滅します。実験用の文書で \caption[Short entry for the list]{A long caption that is only shown under the figure} と書いて \listoffigures を出すと、.lof ファイルには短いほうだけが記録されます。数式や \cite を含む長いキャプションでは、角括弧側を素朴な文にしておくと目次の組版事故も防げます。

caption パッケージを読み込むと、二つの変種が使えるようになります。\caption*{…}番号を付けず、図目次にも載せない キャプションで、口絵や章扉の図に向きます。\ContinuedFloat は、大きな図を複数のフロートに分けたときに 前のフロートと同じ番号を引き継がせる 命令です。\begin{figure} の先頭に \ContinuedFloat を書いてから \caption{Continued} とすると、印刷されるのは「図 1(続き)」ではなく、番号がそのまま「図 1」のもう一枚になります。数ページにまたがる大きな一覧図を、番号を増やさずに分割したいときの定石です。

latex
% short entry for the list, full text under the figure
\caption[Measured values and the model]{Measured values (dots) against the
  theoretical curve (solid). Error bars are one standard deviation.}

% no number, no entry in the list of figures
\caption*{Frontispiece}

% second sheet of a split figure keeps the previous number
\begin{figure}
  \ContinuedFloat
  \centering\includegraphics[width=\linewidth]{survey-part2}
  \caption{Continued}
\end{figure}

caption パッケージで体裁を整える — \captionsetup

書体・番号と本文の区切り・行揃えを変えたいときは caption パッケージを使います。作者は Axel Sommerfeldt で、著作権表示は 1994 年にさかのぼり、TeX Live 2024 に入っているのは 2023 年 8 月の v3.6o です。三十年にわたって一人の手で維持されてきた道具ということになります。\usepackage{caption} と読み込み、\captionsetup{キー=値, …} で指定します。プリアンブルに書けば文書全体、フロートの内側に書けば そのキャプション一つだけ に効くのがこの命令の要点です。

キー主な値働き
formatplain / hang本文の組み方。hang は 2 行目以降を番号の幅だけ字下げする
labelsepcolon / period / space / quad / newline番号と本文の区切り。既定は colon(コロンと空き)
fontsmall / footnotesize / it …キャプション全体の書体とサイズ
labelfontbf / sc / it …「Figure 1」の番号部分だけの書体
textfontit / rm …説明文の本文だけの書体
justificationjustified / centering / raggedright行揃え。既定は両端揃え
width長さ(例 0.8\textwidthキャプションの折り返し幅を狭める
singlelinechecktrue / false既定は true。1 行に収まるキャプションを justification に関係なく中央寄せする

最後の singlelinecheck は、意図と食い違いやすい既定値です。justification=raggedright と書いたのに短いキャプションだけ中央に寄る、という現象はこれが原因で、1 行に収まるキャプションは自動的に中央寄せされます。常に左揃えにしたいなら singlelinecheck=false を添えてください。図と表で体裁を分けたいときは、\captionsetup[figure]{…}\captionsetup[table]{…} のように 角括弧でフロートの種類を指定 します。学会テンプレートが既に \captionsetup を持っていることも多いので、追加する前に上書きしていないか確かめるのが安全です。

latex
\usepackage{caption}
\captionsetup{labelfont=bf, labelsep=period, font=small,
              justification=raggedright, singlelinecheck=false}

% different rules per float type
\captionsetup[figure]{justification=centering}
\captionsetup[table]{font=footnotesize}

フロートの外でキャプションを付ける — \captionof

フロートに乗せずに図を本文のこの位置に固定したい、しかし番号と参照は普通に効かせたい——そのための命令が \captionof{種類}{本文} です。\caption が使えない minipagecenter の中でも、\captionof{figure}{…} と書けば figure カウンタが進み、図目次にも載り、\ref も正しく効きます。実際に minipage の中でこれを使って組むと、直前の figure フロートが「図 1」なら続けて「図 2」になり、.lof にも一行増えます。フロートの機構だけを外して、番号付けの機構はそのまま使う というのが、この命令の要点です。

注意点がひとつ。\captionof は LaTeX 標準の命令ではないので、caption を読み込まずに書くと ! Undefined control sequence. になります。キャプションの体裁は変えたくないがこの命令だけ欲しい、という場合には軽量の capt-of パッケージがあり、\captionof だけを提供します。なお \captionof を使うときも、\label\captionof後ろ に置くという規則はそのままです。

latex
\usepackage{caption}   % or the lightweight capt-of

\begin{center}
  \includegraphics[width=0.5\textwidth]{diagram}
  \captionof{figure}{A figure fixed in the text, outside any float}
  \label{fig:inline}
\end{center}

subcaption で図を (a)(b) に分ける

一つの図の中に小さな図を並べ、それぞれに (a)(b)(c) と小見出しを付ける——現在の標準は subcaption パッケージで、これも Sommerfeldt の作です。\usepackage{subcaption} と書けば裏で caption も読み込まれるので、二つを両方書く必要はありません。主役は subfigure 環境(表なら subtable)で、幅を必須引数として \begin{subfigure}[b]{0.45\textwidth} のように与えます。中身は実質的に minipage で、\includegraphics\caption を入れます。subfigure の中の \caption は (a)(b) の小見出しになり、外側に置いた \caption が図全体の番号を受け持ちます。

latex
\usepackage{graphicx}
\usepackage{subcaption}   % loads caption itself

\begin{figure}
  \centering
  \begin{subfigure}[b]{0.45\textwidth}
    \centering
    \includegraphics[width=\linewidth]{before}
    \caption{Before}
    \label{fig:before}
  \end{subfigure}
  \hfill
  \begin{subfigure}[b]{0.45\textwidth}
    \centering
    \includegraphics[width=\linewidth]{after}
    \caption{After}
    \label{fig:after}
  \end{subfigure}
  \caption{Before and after processing}
  \label{fig:compare}
\end{figure}

この例を組むと、図全体が「図 1」、二つのサブ図が「(a) Before」「(b) After」になります。本文からは \ref{fig:compare} が「1」を、\ref{fig:before}「1a」 を返します——サブ図への参照は図番号と小見出しの連結です。(a) の部分だけが欲しいときは \subref{fig:before} で「a」、\subref*{fig:before} で「(a)」が得られます。もう一つ、一行で書ける \subcaptionbox[目次見出し]{小見出し}[幅][内部位置]{中身} もあります。こちらは書式の都合上 \label を小見出しの引数の中に 入れる点が違い、\subcaptionbox{Before\label{fig:before}}{\includegraphics{…}} のように書きます。画像を一枚入れるだけのサブ図なら、minipage を数行書くより短く済みます。

subfigure・subfig・subcaption — 三世代と、黙って壊れる衝突

サブ図のパッケージは三世代あり、名前が似ているせいで取り違えが絶えません。最古の subfigure は廃止扱いで \subfigure 命令を使い、その後継の subfig\subfloat 命令を提供しますが、こちらももう積極的には保守されていません。新規の文書は subcaption を選んでください。問題は移行の途中に起きます——テンプレートが subfig を読み込んでいるのに気づかず subcaption を足す、という事故です。

この衝突が厄介なのは、読み込んだ時点では何も起きない ことです。両方をプリアンブルに並べても、subcaption はログに Package subcaption Info: The counter 'subfigure' was already defined by... と情報行を書くだけで、警告もエラーも出しません。そして自分の subfigure 環境の定義をあきらめます。文書は無事に進み、最初の \begin{subfigure} に差しかかった瞬間に ! LaTeX Error: Environment subfigure undefined. で崩れ、その後は Missing numberIllegal unit of measure が連鎖します。つまり エラーの発生地点は原因の場所ではありません。この症状を見たら、まずプリアンブル全体を subfigsubfigure で検索してください。学会テンプレートを使っているときはとくにその可能性が高くなります。

  • subcaption — 現在の標準。subfigure / subtable 環境、\subcaptionbox\subrefcaption を自動で読み込む。
  • subfig — 前世代。\subfloat 命令。既存文書では動くが、新規には選ばない。
  • subfigure — 最古。\subfigure 命令。廃止扱いなので使わない。
  • 併用は不可 — どれか一つだけ。テンプレートが既に読み込んでいないか、追加する前に確認する。