Overfull / Underfull \hbox

Overfull \hboxエラーではなく警告 です。LaTeX の実行は最後まで走りきり、PDF はちゃんと出来ています——ただ、どこかの一行が右マージンからはみ出している。だから最初にやるべきことは、ログを睨むことではなく PDF を開いてその行を見ること です。そのうえで、(71.93637pt too wide) の数字が何を意味するのか、in paragraph at lines 4--9detected at line 3 の違いは何か、\hbadness\tolerance\emergencystretch のどれを触るべきか、そして「overfull hbox を消す」といっても 本当に直す のと 警告だけ黙らせる のはまったく別の操作だということを順に見ていきます。裏返しの警告 Underfull \hbox と、縦方向の Overfull \vbox もこのページで扱います。

(71.93637pt too wide) の数字は何を測っているか

その行が \hsize(段の幅)を超えた量、単位はポイント。1pt は約 0.35mm ですから、0.5pt なら肉眼では見えず、70pt なら親指の幅ほど紙面からはみ出しています。この数字だけで対応の優先度が決まります——数 pt 以下なら誰も気づきませんし、実際 LaTeX は 0.1pt までは既定で黙っています(\hfuzz=0.1pt)。TeX が組版する単位は「箱」で、一行分の文字を横に詰めた箱が水平箱、すなわち \hbox です。行分割のときに箱の中身が幅より広くなってしまい、しかもそれ以上詰められなかった——それが Overfull \hbox の正体です。行が詰まりきらない理由はほぼ常に一つ、その行のどこにも折れる場所がなかったことです。

警告の後半、in paragraph at lines 4--9 のような部分は どこで起きたか を示します。この書き方は 4 種類あり、どれが出たかで探す場所が変わるので、次の表で見分けてください。実測は TeX Live 2024 の pdfLaTeX で、それぞれ最小のファイルを作って再現したものです。とくに has occurred while \output is active は「ページを組み立てている最中」という意味で、原因の行が本文のどこにも書いていないことがあり、いちばん厄介です。逆の落とし穴もあります——素の \mbox{...}\makebox[2cm]{...} は、中身がどれだけはみ出しても 警告を一切出しません。これらが詰め物に使う \hss は無限に縮められるので、TeX から見れば箱は常にぴったり収まっている。マージンを踏み越えた文字が、ログには何の痕跡も残さずに印刷されます。

報告の形意味どこを見るか
in paragraph at lines A--Bふつうの段落の行分割で起きたA 行から B 行の段落。もっとも多い
detected at line N段落ではなく幅を固定した箱で起きた\hbox to\makebox[…][s]・パッケージが組んだ箱。N 行目
in alignment at lines A--B表組みの桁揃えで起きたtabular*tabularx など幅を指定した表
while \output is activeページを組み立てている最中に起きたヘッダ・フッタ・脚注・float。行番号は当てにならない

ログは犯人の行を見せてくれる——ハイフンの位置まで

警告のすぐ下に、はみ出した行の中身がそのまま印字されます。 しかも TeX が見つけたハイフネーション位置に - が入った状態で。これが診断の要です。次は幅 4cm の段に英文を流し込んだときの実際のログですが、Wis-senschaft-skol-leg にはハイフンが入っているのに、electroencephalography- にはひとつも入っていません。TeX は明示的なハイフンを含む語を自動ハイフネーションの対象から外します\hyphenchar の走査が明示的なハイフンで止まるため)。つまりこの行は「折る場所が本当に無い」のであって、\tolerance をいくら上げても解決しません。ログのハイフンを見れば、ハイフネーションが試みられているのか、そもそも諦められているのか が一目で分かります。ハイフンがどこにも入っていない場合、言語設定が間違っている疑いも濃厚です。

log
Overfull \hbox (13.35585pt too wide) in paragraph at lines 4--9
\OT1/cmr/m/n/10 The Wis-senschaft-skol-leg pub-
 []

Overfull \hbox (80.27266pt too wide) in paragraph at lines 4--9
\OT1/cmr/m/n/10 li-ca-tion de-scribes an electroencephalography-
 []

PDF 上で該当箇所を目で確かめたいときは、クラスオプションに draft を付けます。article.cls には \DeclareOption{draft}{\setlength\overfullrule{5pt}} と書かれていて、はみ出した行の右端に幅 5pt の黒い罫が出ます。ふだんこの黒罫が出ないのは、latex.ltx が最後に \overfullrule 0pt を実行して INITEX の既定値 5pt を打ち消しているからです。つまり 黒い罫は消されているだけで、いつでも呼び戻せますdraft を付けたくない場合は、プリアンブルに \overfullrule=5pt と直接書いても同じことです(提出前に戻すのを忘れずに)。

二段組み・表・コード——狭い段が overfull を量産する理由

段が狭いほど、折れない語の相対的な長さが致命的になるからです。 幅 10cm の段なら 3cm の語は行の三割ですが、幅 4cm の段では行より長く、どう折っても必ずはみ出します。同じ原稿を一段組みから二段組みに変えたとたん警告が何十件も増えるのは、文章が悪くなったからではなく、段が半分になったからです。以下は overfull が集中して発生する場所で、心当たりがあればまずそこから見てください。段が狭いのが原因だと分かれば、対処も変わります——\sloppy を段落ごとに撒くより、その表だけ p{} 列の幅を見直すほうが早いことがよくあります。

  • 二段組み\documentclass[twocolumn]multicol)。段幅がおよそ半分になるので、一段組みでは問題なかった語が一斉にはみ出す。
  • 表の p{}m{}b{}tabularx。列幅は著者が数値で決めるため、内容に対して狭すぎることがよくある。
  • 逐語環境verbatim\verblistings)。空白も改行も原稿のままなので、TeX には折る余地がまったくない。
  • URL・DOI・ファイルパス・型番・化学名・遺伝子名。空白を含まない長い文字列は、それ自体が一つの語として扱われる。
  • 行内数式。数式は既定では二項演算子や関係子の後ろでしか折れず、\frac の中などでは折れない。
  • 脚注と図表のキャプション。本文より狭い幅で組まれることがあり、\output is active の形で報告されやすい。

overfull hbox を消す——優先順位の高いものから

一語書き換えるのが最良の対処です。 味気ない答えですが、著者にしかできない唯一の解決であり、しかもたいてい五秒で終わります。長い語を短い同義語に替える、語順を入れ替える、あるいは長い型番を脚注に逃がす——それだけで箱は収まります。この順序には理由があって、TeX の行分割は 段落全体を一度に見る アルゴリズム(クヌースとマイケル・プラスが 1981 年の論文「Breaking Paragraphs into Lines」で発表したもの)だからです。段落の最後の一語を変えると、最初の行の折れ方まで変わり得ます。逆に言えば、著者が一語動かすだけで組版側の自由度は大きく広がる。以下は効果と副作用のバランス順に並べた対処です。

  • 言い換える。 一語で済むことが多く、副作用ゼロ。長い型番・製品名は脚注か表へ逃がす。
  • 言語設定を確かめる。 ドイツ語やフランス語の本文に英語のハイフネーションパターンが当たっていると、折れる場所が見つからない。babel なら \usepackage[ngerman]{babel}、XeLaTeX/LuaLaTeX なら polyglossia\setmainlanguage{german}
  • その語だけ折れるようにする。 \- を語中に置くと任意ハイフンになり、\hyphenation{Wis-sen-schafts-kol-leg} はプリアンブルで例外を登録する。明示的ハイフンを含む複合語には \hspace{0pt} を挟むと折れる余地が生まれる。
  • \sloppysloppypar 環境。 段落単位で語間を緩める。\sloppypar は環境として使え、影響範囲を閉じられるので \sloppy より安全。
  • \emergencystretch を上げる。 実測では \emergencystretch=3em だけで overfull 5 件が 0 件になった(代わりに underfull が 7 件出た)。副作用は語間の間延びで、はみ出しより目立たない。
  • microtype を読み込む。 文字の微妙な突き出しと字幅伸縮で、はみ出し量が実測 13.4pt→8.9pt、80.3pt→74.9pt に減った。ただし「減らす」であって「消す」ではない。
  • 最後の手段として \linebreak\mbox 手で折る位置を指定する方法。文章を書き換えると位置がずれるので、提出直前の微調整に限る。

\tolerance\emergencystretch\hbadness\hfuzz の役割分担

前の二つは組版そのものを変え、後ろの二つは警告の出方だけを変えます。 この区別を取り違えると、「直したつもりで実は隠しただけ」という事故が起きます。\hfuzz を大きくすればはみ出しの報告は消えますが、紙面の文字は一ミリも動きません。TeX の行分割は三段構えで、まず \pretolerance の範囲でハイフンなしに試し、だめなら \tolerance の範囲でハイフンを入れて試し、それでもだめなら \emergencystretch の分だけ余分に伸ばして三度目を試みます。\emergencystretch が効くのはこの三度目の走査で、「もう他に手がない」段階の最後の切り札という位置づけです。LaTeX の既定値は latex.ltx\tolerance=200\hbadness=1000\hfuzz=0.1pt と書かれています。よく使われる \sloppy の正体も同じファイルにあり、\tolerance 9999\emergencystretch 3em\hfuzz .5pt\vfuzz\hfuzz4 つの代入だけ です。つまり \sloppy は「許容度を上げる」だけの命令ではなく、\emergencystretch の設定を含んでいます——実測でも、\emergencystretch=3em 単体と \sloppy の結果は同一でした。

パラメータLaTeX の既定値何をするか
\tolerance200許容できる行の悪さの上限。上げると組版が変わる
\emergencystretch0pt3 度目の走査でだけ加わる余分な伸縮。組版が変わる
\hbadness1000これを超えた行だけ underfull を報告。組版は変わらない
\hfuzz0.1ptこの幅までのはみ出しは報告しない。組版は変わらない
\overfullrule0ptはみ出した行の脇に引く黒罫の幅。draft で 5pt になる
preamble
% changes the typesetting -- use these to actually fix boxes
\emergencystretch=3em     % last-resort stretch on the third pass
\usepackage{microtype}    % protrusion and font expansion

% changes only the log -- the page looks exactly the same
\hbadness=10000           % never report Underfull \hbox
\hfuzz=1pt                % ignore overhangs below 1pt

長い URL とコードが折れないとき

\url{} で囲むだけでは足りないことがあります。 幅 5cm の段に長い URL を置いた実測では、素の文字列が 79.0pt はみ出し、url パッケージの \url{} にしても 42.4pt と 10.8pt の 2 件が残りました。\url{}/. の後ろでしか折らないため、ホスト名や長いパス片の途中では折れないのです。ここで効くのが二つあり、ひとつは \sloppy の併用で、実測では overfull が 0 件になり、代わりに underfull が出ました(\sloppy に付き物の語間の間延びが代償です)、もうひとつは xurl パッケージで、\usepackage{xurl} を足すだけで overfull も underfull も 0 件 になりました。xurl は URL の任意の位置で折ることを許可します。hyperref は内部で url を読み込むので折れ方は url と同じで、リンクをページ跨ぎで折るには breaklinks オプションが要ります。コードリストの場合は listingsbreaklines=true が対応する設定です。

preamble
\usepackage{hyperref}   % loads url internally; add breaklinks for split links
\usepackage{xurl}       % allows a break at any point inside a URL
...
\url{https://example.org/proceedings/vol12/paper-0037.pdf}

Underfull \hbox (badness N) は逆向きの症状

行が幅に足りず、語間を引き伸ばして埋めた ——それが Underfull \hbox です。緊急度は低く、badness の値が判断材料になります。badness は 0(完璧)から 10000(限界)までの尺度で、10000 は「これ以上悪くなりようがない」という値です。実測では 1590、2050、7667 といった中間値も出ますが、badness 10000 が並ぶときは語間が目に見えて広がっているはずなので、PDF を確認してください。原因は overfull を消そうとした操作の副作用であることが多く、\sloppy\emergencystretch を入れると overfull が underfull に置き換わります(実測で 5 件→0 件、underfull 0 件→7 件)。それ以外では、段落の途中に \linebreak\\ を入れて短い行を強制したときにも出ます。\linebreak は「ここで折れ、ただし行幅は埋めよ」という意味なので語間が伸び、\newline\\ は「ここで行を終える」なので伸びません。中途半端な行を作りたいときは \\ を使う のが正解です。警告だけを黙らせたいなら \hbadness=10000 で消えますが、紙面は一切変わりません。

Overfull \vbox (… too high)Underfull \vbox

同じ話が縦方向にもあり、単位が「幅」ではなく「高さ」になります。 Overfull \vbox (56.90552pt too high) は、決まった高さの縦箱に中身が入りきらなかったという意味です。実測では \vbox to 1cm{\hrule height 3cm} のような明示的な箱で detected at line 3 の形で出ます。実務でよく見るのはページを組み立てるときで、\textheight より背の高い図や \rule を置くと Overfull \vbox (85.35828pt too high) has occurred while \output is active が出ました。この形が出たら、まず疑うべきは 1 ページに収まらない大きさの図 です。Underfull \vbox (badness 10000) はその逆で、縦の空きを伸ばして高さを埋めたという意味。\flushbottom(book クラスの既定)では各ページの下端を揃えるために縦の空きが伸ばされるので、内容の少ないページで出やすくなります。気にしないなら \raggedbottom に切り替えるか、\vbadness\vfuzz で報告の閾値を上げます——ここでも 閾値を上げても紙面は変わらない という原則は同じです。図が入りきらないときは \enlargethispage でそのページだけ本文領域を伸ばす手もあります。