Die Tabelle ragt aus dem Satzspiegel – die Overfull \hbox, die jeder früher oder später zu sehen bekommt. Hier ist sie, gemessen. Eine zwölfspaltige booktabs-Tabelle in article misst 404,83pt gegenüber einer \textwidth von 345pt, und das Log meldet Overfull \hbox (74.83432pt too wide). Die meisten greifen jetzt zu \small und stellen fest, dass es nicht reicht: Selbst \scriptsize (7pt) lässt die Tabelle bei 351,90pt stehen, immer noch zu breit. Der Grund: Eine kleinere Schrift verkleinert nicht den Abstand zwischen den Spalten. Diese Seite versammelt alle Wege, die Tabelle aufs Papier zu bekommen: die Breite mit tabularx und tabulary deklarieren, sie mit tabularray (Umgebung tblr) neu bauen, sie mit \resizebox und adjustbox skalieren, die Seite mit pdflscape und rotating quer stellen und sie mit \makebox in die Ränder laufen lassen.
Warum eine kleinere Schrift den Überlauf nicht stoppt
Weil \tabcolsep, der Abstand zwischen den Spalten, eine absolute Länge ist, die eine Schriftgrößenänderung nicht berührt. Eine zwölfspaltige Tabelle bekommt \tabcolsep an vierundzwanzig Stellen – 6pt auf jeder Seite jeder Spalte, die beiden Außenkanten eingeschlossen. Setzt man dieselbe Tabelle mit \tabcolsep=0pt, werden aus 404,83pt genau 260,83pt: eine Differenz von exakt 144pt, also waren 35% der Tabelle Polsterung. Diese 144pt schrumpfen bei kleinerer Schrift um keinen einzigen Punkt – gemessen bei \scriptsize betrug die Polsterung weiterhin 144pt. Deshalb kommt die Tabelle nur bis 351,90pt hinunter.
| Maßnahme | Gemessene Tabellenbreite (textwidth = 345pt) | Ergebnis |
|---|---|---|
(none) | 404,83pt | Overfull \hbox (74.83432pt too wide) |
\small | 385,27pt | immer noch zu breit |
\footnotesize | 365,70pt | immer noch zu breit |
\scriptsize | 351,90pt | selbst bei 7pt noch zu breit |
\tabcolsep=3pt | 332,83pt | passt, und die Schrift bleibt bei 10pt |
\resizebox | 345,01pt | passt, doch die Schrift schrumpft auf effektiv 8,52pt |
Die Tabelle verrät die Arbeitsreihenfolge: zuerst die Polsterung kürzen, dann den Spaltenentwurf überdenken und erst danach skalieren oder drehen. Allein \tabcolsep auf 3pt bringt die Tabelle auf 332,83pt, und die Schrift bleibt bei den gut lesbaren 10pt des Fließtexts – hier fängt man also an (\tabcolsep und @{} behandelt ausführlich „Spaltenspezifikation, Ausrichtung und Breite“). Doch irgendwann ist kein Weißraum mehr zu holen. Liegt es nicht an Zahlen, sondern an einer Spalte mit langem Fließtext, hilft kein Kürzen: Die Spalte selbst muss umbrechen. Davon handelt der nächste Abschnitt.
tabularx: erst die Breite festlegen, dann die X-Spalte dehnen
tabularx nimmt die Zielbreite der Tabelle als erstes Argument und lässt die X-Spalten den Rest füllen: \begin{tabularx}{width}{column spec}. Ein X ist eine p-Spalte, die den Restplatz automatisch aufnimmt; mehrere davon teilen ihn gleichmäßig. Rührt der Überlauf von langem Beschreibungstext her, ist das der kürzeste Ausweg – deklariert man die Breite als \textwidth, kann die Tabelle konstruktionsbedingt nicht überlaufen. Es stammt von David Carlisle, dem Autor von longtable, und gehört zum tools-Bundle, ist also bereits installiert.
Der Mechanismus ist etwas ungewöhnlich: tabularx bestimmt die Breiten, indem es die Tabelle mehrfach setzt. Zuerst bekommt jede X die volle Zielbreite, wodurch die Tabelle zu breit wird; dann wird der Überschuss durch die Zahl der X-Spalten geteilt, jede entsprechend verschmälert und neu gesetzt – bis zur Konvergenz. Am Ende wird X zu dem, was \tabularxcolumn definiert; die Vorgabe lautet \newcommand{\tabularxcolumn}[1]{p{#1}}, also eine oben ausgerichtete Absatzspalte. Für vertikal zentrierte Zellen definiert man sie mit m{#1} neu. Eine X-Zelle ist standardmäßig im Blocksatz; für Linksbündigkeit stellt man >{\raggedright\arraybackslash}X voran. Entscheidend ist \arraybackslash, das die Umdefinition von \\ durch \raggedright und Verwandte rückgängig macht. Wer denselben Vorsatz mehrfach schreibt, gibt ihm mit \newcolumntype einen einbuchstabigen Alias, und die Deklaration wird wieder lesbar.
\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}Zwei Einschränkungen. Erstens können, weil der Rumpf mehrfach expandiert wird, Befehle mit Nebenwirkungen – Zähler erhöhen, Dateien schreiben, \footnote, \verb – in tabularx fehlerhaft reagieren. Der übliche Ausweg ist, eine solche Zelle in eine Box oder eine minipage zu packen. Zweitens kennt einfaches tabularx keine Gewichtung: X X teilt immer gleichmäßig, und für 2:1 braucht es entweder X[2] aus tabularray weiter unten oder ein von Hand gerechnetes p{} über \newcolumntype.
tabulary: die Breite nach der Inhaltsmenge verteilen
Während tabularx seine X-Spalten gleichmäßig teilt, verteilt tabulary die Breite proportional zur natürlichen Breite des Spalteninhalts. Steht in einer Spalte ein kurzes Label und in der anderen eine lange Beschreibung, wirkt gleiche Teilung ungeschickt. Die Syntax entspricht sich: \begin{tabulary}{width}{column spec}, mit vier Spaltentypen – L links, C zentriert, R rechts, J Blocksatz. Gewöhnliche l, c, r und p{width} lassen sich mischen, werden aber nicht gemessen und behalten ihre natürliche Breite. Jede gemessene Spalte wird nach der natürlichen Breite ihrer breitesten Zelle gewichtet und so skaliert, dass die Tabelle die gewünschte Gesamtbreite erreicht; eine Spalte, die ohnehin schmaler ist als ihr Anteil, bleibt unverändert. Damit die Verteilung nicht ausufert, begrenzen \tymin (Vorgabe 10pt) und \tymax (Vorgabe 2\textwidth) eine gemessene Spalte – das Sicherheitsventil gegen einen einzelnen absurd langen Eintrag.
\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}Beide Spalten sind hier L, doch „Term“ mit seinem kurzen Inhalt wird schmal und „Description“ mit viel Text bekommt den größeren Anteil. Mit tabularx und X X wären sie identisch breit; für eine Label-plus-Text-Tabelle wirkt tabulary daher natürlicher. Auch tabulary verarbeitet den Rumpf aber mehr als einmal, sodass dieselbe Vorsicht bei Fußnoten und Zählern gilt.
tabularray: die tblr-Umgebung vereint Breite und Linien in einer Syntax
tabularray bündelt in einer einzigen Schlüssel-Wert-Schnittstelle, wofür früher array, booktabs, multirow, colortbl und diagbox zusammenspielen mussten. Geschrieben hat es Jianrui Lyu (lvjr); es verwirft die alte \halign-Technik und analysiert und setzt Tabellen direkt mit LaTeX3 (expl3). Die Fassung in TeX Live 2024 trägt das Datum 2024-02-16, interne Version 2024A. Hauptumgebung ist tblr, geladen mit \usepackage{tabularray}.
Die Struktur von tblr unterscheidet sich etwas von tabular: Vor dem Rumpf steht ein Argument mit durch Kommas getrennten Schlüssel-Wert-Optionen, die innere Spezifikation, wie in \begin{tblr}{ … inner spec … }. Die Spaltenausrichtung deklariert der Schlüssel colspec. Die bekannte Einbuchstabenform colspec={lcr} funktioniert weiterhin, doch die eigentliche Stärke liegt in Q[…], einer allgemeinen Spalte mit Ausrichtung, Breite und weiteren Optionen in eckigen Klammern, und X[…], einer dehnbaren Spalte wie bei tabularx. X[c] ist eine zentrierte dehnbare Spalte, X[2,l] eine linksbündige mit Koeffizient 2, doppelt so breit wie ein normales X. Im Zusammenhang mit Überläufen zählt vor allem, dass width= und colspec= in denselben Klammern stehen und dass diese Koeffizienten das Verhältnis festlegen. Gemessen ergab ein tblr mit width=\textwidth und colspec={X[2,l] X[1,r] X[1,r]} eine Box von genau 345,0pt – exakt die Zielbreite.
Die Breite, in die sich die X-Spalten ausdehnen, gibt der Schlüssel width an (ohne Angabe \linewidth). Abstände zwischen Zeilen und Spalten steuern rowsep und colsep, in tblr standardmäßig rowsep=2pt und colsep=6pt. Linien sind deklarativ: hlines / vlines zeichnen alle horizontalen / vertikalen Linien, und hline{n} / vline{n} formatieren eine bestimmte Linie, etwa hline{2}={1pt,solid} (Z ist der spezielle Index für die letzte Zeile). Im Rumpf schreibt man kein \hline. Wiederkehrende Einstellungen lassen sich mit \SetTblrInner{rowsep=2pt} herausziehen.
Zellspannen werden im Rumpf mit \SetCell gesetzt. \SetCell[c=2]{c} ist eine zentrierte Zelle über 2 Spalten (entspricht \multicolumn), \SetCell[r=2]{c} spannt 2 Zeilen (entspricht \multirow); c= und r= geben Spalten- bzw. Zeilenspanne an, das Argument in Klammern die Ausrichtung. Ganze Zeilen oder Spalten gestaltet man mit \SetRow und \SetColumn; \SetRow{cyan8} färbt eine Zeile blass cyan, die Farbnamen sind im Paket eingebaut. Dasselbe lässt sich auch aus der inneren Spezifikation heraus deklarieren, als row{1}={font=\bfseries}, column{2}={halign=r}, cell{2}{3}={c=2} – das hält den Rumpf sauber.
\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}Dieses tblr fixiert die Tabellenbreite mit width=\textwidth auf die Textbreite. Die drei Spalten sind Q[l] (linke Basisspalte), X[c] (zentrierte dehnbare Spalte) und X[2,l] (linke dehnbare Spalte mit Koeffizient 2); die zwei X-Spalten teilen die Restbreite daher 1 : 2, und Spalte 3, „Description“, wird am breitesten. Im Rumpf steht kein \hline: Die Linien kommen allein aus den hline{…}-Schlüsseln der inneren Spezifikation. Die erste Zeile wird mit row{1}={font=\bfseries} fett, und die Zelle „Table environment“ in Spalte 1 spannt mit \SetCell[r=2]{l} zwei Zeilen. So weit zu kommen, ohne booktabs, multirow und array hinzuzuziehen, ist genau der Reiz von tabularray.
Ist die Tabelle nicht nur breit, sondern auch lang, übernehmen zwei abgeleitete Umgebungen. longtblr ist ein seitenübergreifendes tblr mit wiederholten Kopfzeilen, Captions und Fußnoten; talltblr ist eine einseitige Tabelle mit Anmerkungen darunter, im Geist von threeparttable. In beiden kommen Caption, Label, note{…} und Ähnliches in das optionale Argument […] vor dem Rumpf, die äußere Spezifikation. Eine Kopfwiederholung in longtblr ist schlicht rowhead=1 – eine schlichte Zeilenzahl – und damit knapper als die vier Marker von longtable.
resizebox lügt über die Schriftgröße
\resizebox{\textwidth}{!}{...} aus graphicx skaliert seinen Inhalt als Ganzes auf die genannte Breite. Es ist der schnellste Weg, eine Tabelle aufs Papier zu bekommen – und es verkleinert die Schrift um einen Faktor, der nirgends im Quelltext steht. Gemessen: Gibt man die 404,83pt breite Tabelle an \resizebox{\textwidth}{!}, entsteht eine Box von 345,01pt Breite, und die Höhe fällt von 26,07pt auf 22,22pt. Beide Verhältnisse ergeben 0,8522. Was man für 10pt hält, steht also mit 8,52pt auf dem Papier. Im Dokument steht \documentclass[10pt], auf dem Papier 8,52pt – ein Unfall überall dort, wo Gutachter oder Einreichungsrichtlinien die Schriftgröße prüfen.
Warum passt \resizebox, wo \scriptsize (7pt) versagt? Aus demselben Grund wie oben auf dieser Seite: \resizebox verkleinert die Polsterung zwischen den Spalten mit. Eine Schriftgrößenänderung nimmt jenen 144pt keinen einzigen Punkt, eine Skalierung um 0,8522 drückt sie auf 122,7pt. So schlägt scheinbare 8,52pt-Schrift unter \resizebox echte 7pt unter \scriptsize. Umgekehrt: \resizebox erzeugt eine Tabelle, deren Polsterung ebenfalls zusammengequetscht ist – ein doppelter Nachteil für die Lesbarkeit.
Und \resizebox hat eine viel augenfälligere Falle: Gibt man ihm eine kleine Tabelle, vergrößert es sie. Gemessen kam eine winzige Tabelle von 4,44pt Breite aus \resizebox{\textwidth}{!} mit 345,46pt heraus – ein rund achtundsiebzigfach gedehntes Ungetüm. Setzt man es reflexhaft auf jede Tabelle, wie man es bei \includegraphics tut, blähen sich die schmalen auf. Hier verdient adjustbox mit max width=\textwidth sein Geld: Dieselbe 4,44pt-Tabelle blieb bei 4,44pt, und nur die 404,83pt breite ging auf 345,01pt zurück. Nur verkleinern, wenn nötig, und nie vergrößern – in echten Dokumenten die sicherere Voreinstellung.
\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}Die Seite querstellen: lscape, pdflscape und rotating im Vergleich
Nur pdflscape lässt die Seite im PDF-Betrachter tatsächlich kippen. Alle drei drehen den Inhalt um neunzig Grad, über \begin{landscape} oder sidewaystable, doch allein pdflscape schreibt die Anweisung ins PDF, diese Seite gedreht anzuzeigen – den Eintrag /Rotate 90. Hier dasselbe Dokument in drei Fassungen, geprüft mit pdfinfo.
| Paket | Umgebung | Was pdfinfo für rot und Seitengröße meldet |
|---|---|---|
lscape | landscape | auf jeder Seite rot: 0, weiterhin 612 x 792. Nur der Inhalt |
pdflscape | landscape | nur diese Seite rot: 90, 612 x 792. Der Betrachter dreht sie |
rotating | sidewaystable | rot: 0, 612 x 792. Dreht sich als nummerierter Float |
Beachten Sie: In allen drei Fällen bleibt die Seitengröße bei 612 x 792. Nichts wurde physisch quer gestellt, gedreht ist nur der Inhalt. Damit ist die Wahl klar. Für ein PDF, das am Bildschirm gelesen wird, nimmt man pdflscape und erspart der Leserschaft den schiefen Hals; pdflscape lädt lscape und ergänzt das /Rotate, die lscape-Schreibweise gilt also unverändert weiter. Für Gedrucktes und Gebundenes reicht lscape – man dreht eben das Blatt. Soll die Tabelle ein nummerierter Float mit Caption bleiben, nimmt man sidewaystable aus rotating (für Abbildungen sidewaysfigure). rotating bietet zudem die Optionen figuresright und figuresleft für die Drehrichtung.
\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}Die Tabelle in die Ränder laufen lassen: makebox
Der Satzspiegel ist 345pt breit, das Papier hat aber mehr Platz. Mit den Vorgaben von article misst der linke Rand 134,27pt, der rechte 135,03pt – 269pt Weiß stehen neben dem Text leer. Das Idiom, um dorthin auszugreifen, lautet \noindent\makebox[\textwidth]{...}. \makebox steckt seinen Inhalt in eine Box der Breite \textwidth; ist der Inhalt breiter, läuft er gleichmäßig nach beiden Seiten über. Für die 404,83pt breite Tabelle sind das je 29,92pt in jeden Rand: Die Tabelle wird breiter, die optische Mitte der Seite bleibt.
Eines muss man hinnehmen: Da der Inhalt die Box überschreitet, meldet TeX weiterhin Overfull \hbox. Das ist der eine Fall, in dem diese Warnung ignoriert werden darf – der Überlauf ist gewollt. Soll nur eine Seite überlaufen, fixiert \makebox[\textwidth][l]{...} die linke Kante und lässt die Tabelle nach rechts laufen. Kontrollierter geht es mit der Umgebung adjustwidth aus dem Paket changepage, die den Satzspiegel für einen Abschnitt verbreitert; das ist sauberer und hält Fußnoten und Kolumnentitel im Einklang. Die tatsächlichen Randmaße hängen von Papier und geometry ab – prüfen Sie also immer das echte PDF, wenn etwas in den Rand reichen soll (wie die Ränder überhaupt gesetzt werden, behandelt „Ränder und Satzspiegel“).
Die Tabelle teilen: senkrecht schneiden oder transponieren
Es gibt Antworten, die ganz ohne Paket auskommen. Die Spalten auf zwei Tabellen aufteilen und die Schlüsselspalte in beiden wiederholen: Bei zwölf Spalten stehen die Regionsnamen in der ersten Spalte beider Hälften, die Jahre teilen sich in 2–6 und 7–12. Das Auge muss nie über einen Bruch springen, und die Schrift bleibt so groß wie der Fließtext. Nichts wird skaliert, nichts gedreht – oft die lesbarste Lösung überhaupt. Der andere Zug ist das Transponieren. Eine Tabelle mit zwölf Jahren mal fünf Regionen wird breit; fünf Regionen mal zwölf Jahre wird hoch – und hohe Tabellen sind das Ressort von longtable.
Wozu greifen
Die Ursache entscheidet. Läuft eine Textspalte über, nimmt man tabularx – X[2] aus tabularray, wenn die Spalten ungleich gewichtet sein sollen, tabulary, wenn die Teilung dem Inhalt folgen soll; die Breite schlicht zu deklarieren, ist die sauberste Lösung. Ist es ein Dickicht von Zahlenspalten, beginnt man mit \tabcolsep und fragt dann, ob wirklich alle Spalten gleichzeitig gebraucht werden. Müssen tatsächlich alle Spalten auf ein Blatt, nimmt man max width aus adjustbox statt \resizebox. Ist es selbst dafür zu breit, stellt pdflscape die Seite quer. Für eine neu geschriebene Tabelle greift man zu tabularray: Breite, Linien, Farbe und Zellverbünde in einer einzigen Syntax. Ist die Tabelle nicht nur breit, sondern auch lang, geht es weiter zu longtblr oder longtable. Welchen Weg auch immer – schauen Sie am Ende ins fertige PDF und fragen Sie sich, ob eine 8,5pt-Ziffer noch lesbar ist.
| Paket | Wie die Breite festgelegt wird | Geeignet für |
|---|---|---|
tabularx | Feste Gesamtbreite; X-Spalten teilen gleichmäßig | Gleich breite Textspalten auf Zielbreite |
tabulary | Feste Gesamtbreite; nach Inhalt verteilt | Ungleichmäßige Label-plus-Text-Tabellen |
tabularray | width-Schlüssel plus X-Spalten, mit Koeffizienten | Moderne Tabellen mit Linien, Farbe und Spannen aus einem System |
adjustbox | verkleinert nur bei Überlauf (max width) | Eine sichere Obergrenze für bestehende Tabellen |
pdflscape | lässt die Breite unangetastet und dreht die Seite um 90 Grad | Tabellen, die hochkant nie passen |
Die Details der Spaltendeklaration selbst, etwa \multicolumn und >{…} aus dem Paket array, gehören zu „Spaltenspezifikation, Ausrichtung und Breite“, die Grundlagen des Zellverbindens zu „Zellen verbinden“ und sehr lange seitenübergreifende Tabellen zur Seite „longtable“.