表が本文からはみ出す——LaTeX を使っていて誰もが一度は出す Overfull \hbox です。実測しましょう。article の 12 列 booktabs 表は 404.83pt、対する \textwidth は 345pt。ログには Overfull \hbox (74.83432pt too wide) と出ます。ここで多くの人は \small を試しますが、それでは足りません——\scriptsize(7pt)まで落としても 351.90pt で、まだはみ出します。理由は、フォントを小さくしても 列間の余白は縮まないから。このページでは、この表を紙に載せる方法を全部並べます。幅を宣言する tabularx/tabulary、キー=値で組み直す tabularray(tblr)、拡大縮小する \resizebox と adjustbox、ページごと横向きにする pdflscape と rotating、そして余白へはみ出させる \makebox。
なぜ小さくしても表がはみ出るのか
列間の余白 \tabcolsep は絶対値の長さで、フォントサイズを変えても縮まないから です。12 列の表なら、列と列のあいだと表の両端をあわせて \tabcolsep(片側 6pt)が 24 か所ぶん入ります。同じ表を \tabcolsep=0pt で組み直すと 404.83pt が 260.83pt ——差はきっかり 144pt、表幅の 35% が余白だったことになります。この 144pt は文字を小さくしても 1pt も減りません。実際、\scriptsize で組んでも余白の合計は 144pt のままでした。だから 351.90pt までしか下がらないのです。
| 対処 | 実測の表幅(textwidth = 345pt) | 結果 |
|---|---|---|
(none) | 404.83pt | Overfull \hbox (74.83432pt too wide) |
\small | 385.27pt | まだはみ出す |
\footnotesize | 365.70pt | まだはみ出す |
\scriptsize | 351.90pt | 7pt まで落としてもまだはみ出す |
\tabcolsep=3pt | 332.83pt | 収まる。文字は 10pt のまま |
\resizebox | 345.01pt | 収まるが実効 8.52pt まで縮む |
この表から実務の順番が読み取れます。まず余白を削り、次に列の設計を見直し、それでも駄目なら縮小か回転。\tabcolsep を 3pt にするだけで 332.83pt に収まり、しかも本文と同じ 10pt のまま読めるのですから、最初に試すべきはここです(\tabcolsep と @{} の詳細は「列指定・整列・幅」の担当です)。ただし削れる余白には限りがあります。数字ではなく 長い文章が入る列 が原因なら、余白ではなく列そのものを折り返させる必要があります。次節がその話です。
tabularx — 幅を先に決めて X 列に伸ばさせる
tabularx は 表の目標幅を最初の引数に取り、X 列にその残りを埋めさせます。書式は \begin{tabularx}{幅}{列指定}。X は「残りの幅を自動で埋める p 列」で、複数あれば 均等に分け合います。はみ出しの原因が長い説明文なら、これが最短の解決です——幅を \textwidth と宣言してしまえば、定義上はみ出しようがありません。作者は longtable と同じ David Carlisle で、tools バンドルに入っているので追加インストールは不要です。
仕組みは少し変わっています。tabularx は表を 何度か試し組み して幅を求めます。まず X 列を目標幅いっぱいにして組み(はみ出した状態)、超過分を X 列の本数で割って各 X を縮め、また組み直す——収束するまで繰り返します。最終的に X は \tabularxcolumn が定める列に置き換わり、その既定は \newcommand{\tabularxcolumn}[1]{p{#1}}、つまり 上端揃え の段落列です。天地中央にしたければ m{#1} に再定義します。X の中身は既定で両端揃えなので、左寄せにするには列指定に >{\raggedright\arraybackslash}X と前処理を添えます。ここで \arraybackslash が要点で、\raggedright などが \\ の意味を変えてしまうのを元に戻す役目です。同じ前処理を何度も書くなら \newcolumntype で一文字の別名にすると読みやすくなります。
\usepackage{tabularx}
\newcolumntype{Y}{>{\raggedright\arraybackslash}X}
% ...
\begin{tabularx}{\textwidth}{l Y Y}
\hline
Package & Strength & Weakness \\
\hline
tabular & simple and fast & you compute the widths yourself \\
tabularx & the table hits a fixed width & slower: the body is set several times \\
\hline
\end{tabularx}注意点が二つあります。第一に、本文を何度も展開する性質上、tabularx の中では 副作用のある命令 ——カウンタの加算、ファイル書き込み、\footnote、\verb など——が誤動作することがあります。脚注や \verb を入れたいセルは、いったんボックスや minipage に包むのが定石です。第二に、素の tabularx に 比率の指定はありません。X X と書けば必ず等分で、2:1 にしたければ後述の tabularray の X[2] を使うか、\newcolumntype で p{} を手計算するしかありません。
tabulary — 中身の量に応じて幅を配る
tabularx が X 列を 均等に 割るのに対し、tabulary は 各列の中身の自然な幅に比例 させて配ります。片方が短い見出し語、もう片方が長い説明という表では、等分はかえって不格好です。書式は同じく \begin{tabulary}{幅}{列指定} で、列タイプは四つ——L 左寄せ、C 中央、R 右寄せ、J 両端揃え。普通の l・c・r・p{幅} も混ぜられますが、そちらは 測定の対象外 で自然幅のまま残ります。各列は、その列で一番幅広いセルの自然幅で重み付けされ、全体が指定幅になるよう調整されますが、自然幅がすでに小さい列はそのまま置かれます。極端な配分を防ぐために、測定される列の下限 \tymin(既定 10pt)と上限 \tymax(既定 2\textwidth)を調整できます。一語だけ異様に長いセルが列幅を独占するのを抑えるための安全弁です。
\usepackage{tabulary}
% ...
\begin{tabulary}{\textwidth}{L L}
\hline
Term & Description \\
\hline
X column & Shares the width left over after the fixed columns, equally with the other X columns. \\
\hline
\end{tabulary}この二列はどちらも L ですが、中身が短い「Term」は狭く、長文の「Description」は広く配分されます。tabularx に X X と書けば必ず等幅ですから、見出し列+本文列の表では tabulary のほうが自然に見えます。ただし tabulary も本文を複数回処理するので、tabularx と同じく脚注やカウンタには注意が必要です。
tabularray — tblr 環境で幅も罫線も一つの書式に
tabularray は、これまで array・booktabs・multirow・colortbl・diagbox を併用して実現していたことを 一つのキー=値インターフェース に統合したパッケージです。作者は Jianrui Lyu(lvjr)。古い \halign ベースの実装を捨て、LaTeX3(expl3)で表を直接解析・組版します。TeX Live 2024 同梱版は 2024-02-16 リリース、内部バージョン 2024A。主環境は tblr で、\usepackage{tabularray} で読み込みます。
tblr の構造は tabular と少し違います。本体の前に キー=値をカンマで並べた一つの引数(内側指定) を置き、\begin{tblr}{ … 内側指定 … } と書きます。列の整列は colspec キーで宣言します。colspec={lcr} のように従来どおりの一文字指定もできますが、本領は Q[…](整列・幅などのオプションを角括弧で渡す汎用列)と X[…](tabularx 同様の伸縮列)にあります。X[c] は中央寄せの伸縮列、X[2,l] は 係数 2(他の X の倍の幅)で左寄せの伸縮列。はみ出しの文脈でうれしいのは、width= と colspec= が同じ括弧のなかに書ける ことと、この係数で 比率を指定できる ことです。実測すると、width=\textwidth と colspec={X[2,l] X[1,r] X[1,r]} を指定した tblr の出力は きっかり 345.0pt ——目標幅にぴたりと一致しました。
X 列を使うときの展開先の幅は width キーで与えます(未指定なら \linewidth)。行間・列間の余白は rowsep・colsep キーで、tblr の既定は rowsep=2pt・colsep=6pt。罫線は宣言的で、hlines/vlines と書けば全ての横/縦罫線を引き、hline{2}={1pt,solid} のように hline{番号}/vline{番号} で特定の線の太さや種類を指定できます(Z は最終行を表す特別な番号)。\hline を本文に書く必要はありません。よく使う設定は \SetTblrInner{rowsep=2pt} としてまとめて指定できます。
セル結合は本文側で \SetCell を使います。\SetCell[c=2]{c} は 2 列にまたがる 中央寄せセル(\multicolumn 相当)、\SetCell[r=2]{c} は 2 行にまたがる セル(\multirow 相当)で、c=・r= が列・行の連結数、波括弧がそのセルの整列です。行や列をまとめて装飾するには \SetRow・\SetColumn を使い、たとえば \SetRow{cyan8} で行を淡い水色に塗れます(色名はパッケージ内蔵)。内側指定の側から row{1}={font=\bfseries}・column{2}={halign=r}・cell{2}{3}={c=2} と書くこともでき、本文を汚さずに済みます。
\usepackage{tabularray}
% ...
\begin{tblr}{
width = \textwidth,
colspec = {Q[l] X[c] X[2,l]},
rowsep = 3pt,
hline{1,Z} = {1pt,solid},
hline{2} = {0.5pt,solid},
row{1} = {font=\bfseries},
}
Item & Kind & Description \\
\SetCell[r=2]{l} Table environment & fixed width & The table width is fixed; X columns share the rest. \\
& content width & Width is apportioned by how much each column holds. \\
Note & --- & Rules, colour and spans are all set through keys. \\
\end{tblr}この tblr は width=\textwidth で表幅を本文幅に固定します。列は Q[l](左寄せの基本列)、X[c](中央寄せの伸縮列)、X[2,l](係数 2・左寄せの伸縮列)の三本で、二本の X は残り幅を 1 : 2 で分け合うため、3 列目「Description」が最も広くなります。罫線は本文に \hline を書かず、内側指定の hline{…} だけで引いています。先頭行は row{1}={font=\bfseries} で太字、1 列目の「Table environment」は \SetCell[r=2]{l} で 2 行ぶち抜き にしています。booktabs・multirow・array を併用せずともここまで整うのが tabularray の強みです。
表が横だけでなく縦にも長い場合には、二つの派生環境があります。longtblr は複数ページにまたがれる tblr で、見出し行の繰り返し・キャプション・脚注に対応します。talltblr は threeparttable のように表の下に注記を置ける一枚ものです。どちらも、キャプション・ラベル・note{…} などを本体の前の 任意引数 […](外側指定) に書きます。longtblr の見出し繰り返しは rowhead=1 のように 行数を数で指定 するだけで、longtable の四つのマーカーより簡潔です。
resizebox は字の大きさについて嘘をつく
graphicx の \resizebox{\textwidth}{!}{...} は中身を丸ごと拡大縮小して指定幅に合わせます。表を紙に載せる最速の方法ですが、ソースのどこにも書かれない縮小率で文字が小さくなります。実測しましょう。404.83pt の表を \resizebox{\textwidth}{!} に入れると幅 345.01pt、高さは 26.07pt から 22.22pt になりました。比はどちらも 0.8522。つまり 10pt で書いたつもりの文字は、紙の上では 8.52pt です。\documentclass[10pt] と書いてあるのに実物は 8.52pt——査読者や投稿規程がフォントサイズを見る場面では、これは事故になります。
ではなぜ \resizebox は収まるのに \scriptsize(7pt)は収まらないのか。答えは冒頭と同じで、\resizebox は列間の余白ごと縮める からです。フォントサイズの変更は 144pt の余白を 1pt も減らせませんが、0.8522 倍の拡大縮小はその 144pt も 122.7pt に縮めます。だから見かけ 8.52pt の \resizebox が、実物 7pt の \scriptsize に勝ってしまう。逆に言えば \resizebox は 余白まで詰めた表 を作っているので、読みやすさの観点では二重に不利です。
そして \resizebox には、もっと目に見える罠があります。小さい表を渡すと拡大してしまう のです。実測では、幅 4.44pt の小さな表を \resizebox{\textwidth}{!} に入れると 345.46pt ——約 78 倍に引き伸ばされた怪物ができました。\includegraphics の癖でつい全部の表に付けると、狭い表だけ巨大化します。ここで adjustbox の max width=\textwidth が効きます。同じ 4.44pt の表は 4.44pt のまま で、404.83pt の表だけが 345.01pt に縮みました。「必要なときだけ縮め、決して拡大しない」——実務ではこちらを既定にするのが安全です。
\usepackage{graphicx} % \resizebox
\usepackage{adjustbox} % \adjustbox and the adjustbox environment
% ...
% scales in BOTH directions -- a narrow table gets blown up
\resizebox{\textwidth}{!}{\begin{tabular}{...}...\end{tabular}}
% only ever shrinks; a narrow table is left alone
\begin{adjustbox}{max width=\textwidth}
\begin{tabular}{...}...\end{tabular}
\end{adjustbox}ページごと横向きにする — lscape・pdflscape・rotating の違い
PDF ビューアでページごと回って表示されるのは pdflscape だけ です。三つとも \begin{landscape} や sidewaystable で内容を 90 度回しますが、PDF に「このページは回して表示せよ」という指示(/Rotate 90)を書き込むのは pdflscape だけ。同じ文書を三通りで組み、pdfinfo で確認した結果がこれです。
| パッケージ | 使う環境 | pdfinfo が報告する rot と用紙サイズ |
|---|---|---|
lscape | landscape | 全ページ rot: 0、612 x 792 のまま。中身だけ回る |
pdflscape | landscape | 該当ページだけ rot: 90、612 x 792。ビューアが回して表示 |
rotating | sidewaystable | rot: 0、612 x 792。番号付きのフロートとして回る |
どれも 用紙サイズは 612 x 792 のまま で、紙を横長にしているわけではないことに注意してください。回っているのはあくまで内容です。判断はこうなります。画面で読まれる PDF なら pdflscape——読者が首を傾げずに済みます。pdflscape は lscape を読み込んだうえで /Rotate を足すので、lscape の書き方はそのまま通ります。印刷して綴じるなら lscape でも十分で、紙を回せば読めます。表を「表 N」として番号とキャプション付きで置きたいなら rotating の sidewaystable(図なら sidewaysfigure)。rotating は figuresright/figuresleft オプションで回転方向を選べます。
\usepackage{pdflscape} % loads lscape and adds /Rotate 90 to the page
\usepackage{rotating} % sidewaystable / sidewaysfigure
% ...
% a whole page turned sideways in the viewer
\begin{landscape}
\begin{tabular}{...}...\end{tabular}
\end{landscape}
% a rotated float that still says "Table N"
\begin{sidewaystable}
\centering
\begin{tabular}{...}...\end{tabular}
\caption{A very wide table}
\end{sidewaystable}余白へはみ出させる — makebox で本文幅を超える
本文幅は 345pt でも、紙にはもっと余地があります。article の既定では左の余白が 134.27pt、右が 135.03pt ——本文の左右に合計 269pt が空いています。ここへ表を張り出させる定石が \noindent\makebox[\textwidth]{...} です。\makebox は「幅 \textwidth の箱に中身を入れる」命令で、中身のほうが広ければ 左右へ均等にあふれます。404.83pt の表なら片側 29.92pt ずつ余白へ出る計算で、版面の中心は保たれたまま表だけが広がります。
一点だけ覚悟が要ります。箱より中身が広いので、TeX は依然 Overfull \hbox を報告します。これは今回だけは無視してよい警告 です——意図してはみ出させているのですから。片側だけに出したいなら \makebox[\textwidth][l]{...} で左端をそろえ、右へだけあふれさせます。もっと制御したければ changepage パッケージの adjustwidth 環境で、その区間だけ本文幅を広げるほうが行儀がよく、脚注やヘッダとの整合も保てます。なお余白の実寸は用紙と geometry の設定で変わるので、余白へ出す設計をするときは必ず現物の PDF で確認してください(余白そのものの決め方は「余白・版面」の担当です)。
表を割る — 縦に切るか、行と列を入れ替えるか
道具に頼らない解決策もあります。列を二つの表に割り、キーとなる列だけ両方に繰り返す ——12 列の表なら、1 列目の地域名を左右どちらの表にも置いて、2〜6 列目と 7〜12 列目に分けます。読者は視線を左右に往復させずに済み、フォントサイズは本文と同じまま。縮小も回転もしないので、いちばん読みやすい結果になることが多い方法です。もう一つは 行と列を入れ替える こと。「12 年 × 5 地域」の表は横に長くなりますが、「5 地域 × 12 年」にすれば縦に長くなり、こんどは longtable の担当範囲に落ちます。
結局どれを使うか
判断は原因で決まります。長い文章の列があふれているなら tabularx(比率が要るなら tabularray の X[2]、分量に応じた配分なら tabulary)——幅を宣言してしまうのが一番きれいです。数値列が多くてあふれているなら、まず \tabcolsep、次に列を減らすか分割するかを考えます。どうしても全列を一枚に載せる必要があるなら adjustbox の max width(\resizebox ではなく)。それでも入らないほど広いなら、ページごと回して pdflscape。新しく書き始める表なら tabularray が素直で、幅・罫線・色・セル結合を一つの書式で書けます。表が横だけでなく縦にも長いなら longtblr か longtable へ。どの道を選んでも、最後は必ず PDF を目で見て、8.5pt の数字が読めるかどうかを確かめてください。
| パッケージ | 幅の決め方 | 主な用途 |
|---|---|---|
tabularx | 表幅を固定し X 列が均等に分け合う | 本文幅に収める等幅の段落列 |
tabulary | 表幅を固定し内容量で比例配分 | 分量の偏る見出し+本文の表 |
tabularray | width キーと X 列(係数で比率も) | 罫線・色・結合まで一括した現代的な表 |
adjustbox | はみ出したときだけ縮小(max width) | 既存の表に安全な上限をかける |
pdflscape | 幅は変えず、ページを 90 度回す | どうやっても縦置きに入らない表 |
列指定そのものの詳細(\multicolumn・array の >{…} など)は「列指定・整列・幅」、セル結合の基礎は「セル結合」、ページをまたぐ長大な表は「longtable」のページが担当します。