description(定義)

LaTeX の description 環境は、itemizeenumerate と並ぶ三番目のリストでありながら、設計思想がまったく違います。標準クラスの定義を開くと、description\labelwidth0pt に、\itemindentマイナスの \leftmargin に設定しています。つまり「見出し語を入れる欄」の幅は、はじめから存在しないのです。この一行が、description の長所(用語がどれだけ長くても組める)と最大の悩み(長い用語が説明文を押し出してしまう)の両方を同時に説明します。このページでは、description が何を表すための環境なのか、太字はどこから来るのか、そして enumitemstyle= でその押し出しをどう制御するかを見ていきます。

description は何を表すための環境か

description「語」と「その語の説明」の組 を並べるための環境です。itemizeenumerate が印(黒丸や番号)を自動で付けてくれるのに対し、description ではラベルを あなたが言葉で与えます——\item の省略可能引数 [...] に書いた中身が、そのまま見出し語になります。itemizeenumerate では [...] は「この項目だけ印を差し替える」おまけの機能でしたが、description ではここが主役です。用語集、オプション一覧、パラメータの説明、登場人物表——「名前があって、それに説明がぶら下がる」構造なら、これが正しい環境です。

latex
\begin{description}
  \item[TeX] The typesetting system Knuth wrote.
  \item[LaTeX] A document language built on top of TeX.
  \item[CTAN] The worldwide archive network that distributes packages.
\end{description}

この構造は HTML の <dl><dt><dd>(定義リスト)とちょうど対応します。だから description を選ぶことには、見た目を超えた意味があります——原稿のなかで「これは定義である」と宣言していることになり、変換ツールや目次生成ツールがその意図を読み取れます。逆に、太字の見出しと段落を \textbf{用語}\quad 説明 のように手で組んでしまうと、出力は似ていても構造の情報は失われます。なお itemizeenumerate と同じく項目は最低 1 つ必要で、空のまま閉じると ! LaTeX Error: Something's wrong--perhaps a missing \item. になります。

太字はどこから来るのか(\descriptionlabel)

見出し語が太字になるのは \item[...] のせいではなく、description 専用の命令 \descriptionlabel のせいです。標準クラスでの定義は \hspace\labelsep \normalfont\bfseries #1 の一行で、\bfseries がここに書かれています。この区別は確かめられます——itemize の中で \item[Word] と書いた PDF に埋め込まれるフォントは本文用のローマン体だけで、太字は一切現れません。つまり \item[...] は「ラベルを差し替える」だけの機能で、太字にする力は持っていないのです。description の太字は、description 環境が \makelabel\descriptionlabel を差し込むことで初めて生まれます。

したがって enumitem を使わずに書体だけ変えたいなら、\descriptionlabel\renewcommand で再定義するのが正攻法です。引数 #1 が見出し語のテキストになります。次はすべての見出し語をスモールキャピタルにする例で、先頭の \hspace{\labelsep} は元の定義と同じ空きを保つために残しています。\textsc\texttt(等幅)や \textit(イタリック)に替えれば好みの書体になります。なお itemize が階層ごとに印を切り替え、enumerate が階層ごとに番号の形を切り替えるのに対し、description は入れ子にしても見出し語の体裁が変わりません\descriptionlabel は一つしかないので、この再定義は文書中のすべての階層に等しく効きます。

preamble
% the standard-class definition is:
%   \newcommand*\descriptionlabel[1]{\hspace\labelsep \normalfont\bfseries #1}
\renewcommand{\descriptionlabel}[1]{%
  {\hspace{\labelsep}\textsc{#1}}}

長い見出し語が説明文を押し出す理由——labelwidth が 0 だから

長い見出し語は 折り返さず、説明文の 1 行目をそのぶん右へ押し出します。原因は latex.ltx にある一行の分岐で、ラベルの箱が \labelwidth より広ければ(\ifdim \wd\@tempboxa >\labelwidth)、LaTeX は固定幅の箱をあきらめてラベルを 自然な幅 のまま置きます。そして description\labelwidth を 0pt に設定しているので、どんなに短い語でも必ずこの分岐に入ります。つまり description の見出し語は、はじめから固定幅の欄に入っていないのです。article で実測すると、\labelwidth は 0pt、\itemindent は −25.00003pt(= −\leftmargin)、\labelsep は 5pt でした。

実際に組んで測ると、見出し語のあとには常に 5pt——ちょうど \labelsep ぶん——の空きが入り、これはソースで \item[Term]body と詰めて書いても \item[Term] body と離して書いても同じ位置になります。空きはあなたの原稿の空白ではなく \labelsep が作っているので、詰めて書いても救われません。折り返した 2 行目以降は \leftmargin(25pt)まで下がるので、見出し語と説明の 2 行目は左端がそろわず、階段状に見えます。極端に長い語(テキスト幅を超える語)を置くと、Overfull \hbox の警告とともに右余白へはみ出します。見出し語が 3〜4 語を超えるなら、次節の style= で組み方そのものを変えるべき、というのが実務上の判断です。

enumitem の font= と style= で組み方を変える

enumitem を読み込むと description にもオプションを直接渡せるようになり、font= が見出し語の書体を、style= がラベルと本文の並べ方そのものを決めます。font=\sffamily\bfseries と書けばサンセリフの太字に、font=\ttfamily なら等幅になります——\descriptionlabel を書き換えるより短く、しかもリストごとに変えられるのが利点です。leftmargin=labelsep=itemsep= といった他のリストと共通のキーもそのまま使えます。前節の押し出し問題を解くのは style= のほうです。

style の値長い見出し語のときの挙動
standard標準クラスと同じ。ラベルを箱に入れて組み、はみ出したぶんだけ本文を右へ押す
unboxedstandard に近いが、ラベルを箱に入れない。長い語でも詰まらず、行分割もできる
nextlineラベルが余白に収まらなければ、本文は次の行から始まる。本文が左余白に食い込まない
samelinenextline に似るが、ラベルが収まらなくても本文は同じ行に続ける
multilineラベルを labelwidth の幅に折り返し、必要なら分綴して積む。本文は右側にそろう

実際に長い見出し語を五つの style= で組み比べると、違いがはっきり出ます。nextline では長い語のあとで本文が次の行に落ち、sameline では同じ行に続きます。短い語のときは両者とも同じ行に続くので、違いが現れるのは「収まらないとき」だけ です。multiline は劇的で、長い語を labelwidth の幅に折り返し、必要なら分綴(ハイフネーション)まで行って縦に積みます——見出し語が長い技術文書の用語集で、本文の左端を一直線にそろえたいときに効きます。ただしその場合は labelwidth= を明示的に与えないと折り返し幅が決まらないので、leftmargin= と組みで指定してください。

document.tex
\usepackage{enumitem}
% one list only
\begin{description}[font=\bfseries\sffamily, style=nextline, leftmargin=1.5cm]
  \item[A term long enough to overrun its line]
    the explanation begins on the next line instead of being shoved sideways
  \item[Short] the explanation stays on this line
\end{description}

% or once in the preamble, for every description in the document
\setlist[description]{font=\sffamily\bfseries, style=nextline}

角括弧の落とし穴とラベルの省略

[] は省略可能引数の区切りなので、これを 文字として 出したいときは中括弧で包んで隠します。正規表現の文字クラス [a-z] を見出し語にするなら \item[\texttt{[a-z]}]——閉じ括弧を含む場合はさらに注意が要り、\item[閉じ括弧 {]}] のように {]} と書きます。逆に、説明文が [ で始まるときも危険で、\item {[} のように包まないと LaTeX がそれをラベルの開始と誤読します。プログラミング言語の文法を説明する文書では、この二つは頻出します。

latex
\begin{description}
  \item[\texttt{[a-z]}] a character class; brackets in a label need braces
  \item {[}this is how a body starting with a bracket is written
\end{description}

ラベルを 省略すると、その項目にはラベルが付きません——印も字下げの手がかりもない、ぶら下がり段落のような項目になります。description ではラベルこそが要なので、意図した場合を除いて避けてください。気の利いた既定値が存在しない以上、ラベルは必ず自分で与えるものだと考えておくのが安全です。もう一つ、ラベルの中で書体を変える命令を 宣言形 で書くと既定の太字を上書きしてしまうので、\item[{\ttfamily label}] のように命令ごと中括弧で包んでおくと安全です。

description と 2 列の表、どちらを使うべきか

説明が 1 行を超えるなら description、値が短くそろっていて縦に読ませたいなら表、というのが実務上の分かれ目です。tabular の 2 列は「用語と説明」を組むのに一見ぴったりですが、三つの弱点があります。第一に ページをまたげませんlongtable などを持ち出す必要があります)。第二に 列幅を自分で決めなければならずp{5cm} のような固定値は本文の幅を変えたとたんに破綻します。第三に、説明が長くなるほど右列だけが縦に伸び、行と行の境目が見えなくなります。description はどれも起こしません——段落として自然に流れ、ページ分割も自動で、幅は \textwidth に従います。

逆に、値が「型」「既定値」「範囲」のように 複数の属性 を持つなら、それはもう定義リストではなく表です。description は「名前 → 説明」という 1 対 1 の対応にだけ向いています。三つめの列が欲しくなった時点で tabular に移るのが正しい判断で、無理に \item[名前(型・既定値)] と詰め込むと、見出し語が長くなって本節の冒頭で見た押し出しの問題に逆戻りします。