La tabla se sale del bloque de texto: el Overfull \hbox que todo el mundo encuentra tarde o temprano. Aquí está, medido. Una tabla booktabs de doce columnas en article mide 404,83pt frente a una \textwidth de 345pt, y el registro dice Overfull \hbox (74.83432pt too wide). Mucha gente recurre entonces a \small y descubre que no basta: incluso \scriptsize (7pt) deja la tabla en 351,90pt, todavía pasada. El motivo es que encoger la letra no encoge el espacio entre columnas. Esta página reúne todas las maneras de meter esa tabla en el papel: declarar el ancho con tabularx y tabulary, reconstruirla con tabularray (el entorno tblr), escalarla con \resizebox y adjustbox, girar la página con pdflscape y rotating, y dejarla desbordar hacia los márgenes con \makebox.
Por qué encoger la letra no detiene el desbordamiento
Porque \tabcolsep, el espacio entre columnas, es una longitud absoluta que un cambio de cuerpo no toca. Una tabla de doce columnas recibe \tabcolsep (6pt a cada lado) en veinticuatro sitios, bordes exteriores incluidos. Recompón la misma tabla con \tabcolsep=0pt y 404,83pt pasan a 260,83pt: una diferencia de exactamente 144pt, es decir, el 35% de la tabla era relleno. Esos 144pt no se reducen ni un punto al menguar la letra: medido en \scriptsize, el relleno seguía sumando 144pt. Por eso la tabla toca fondo en 351,90pt.
| Remedio | Ancho medido (textwidth = 345pt) | Resultado |
|---|---|---|
(none) | 404,83pt | Overfull \hbox (74.83432pt too wide) |
\small | 385,27pt | sigue pasándose |
\footnotesize | 365,70pt | sigue pasándose |
\scriptsize | 351,90pt | sigue pasándose, incluso a 7pt |
\tabcolsep=3pt | 332,83pt | cabe, y la letra sigue en 10pt |
\resizebox | 345,01pt | cabe, pero la letra baja a 8,52pt efectivos |
La tabla revela el orden de trabajo: primero recortar el relleno, luego repensar el diseño de columnas y solo después escalar o girar. Poner \tabcolsep a 3pt basta para dejar la tabla en 332,83pt manteniendo el cuerpo legible de 10pt del texto, así que ahí se empieza (\tabcolsep y @{} se tratan a fondo en «Especificación de columnas, alineación y anchura»). Pero el blanco recortable tiene un límite. Si el culpable no son las cifras sino una columna con prosa larga, recortar no sirve: la columna misma tiene que ajustarse. De eso trata la sección siguiente.
tabularx: fija primero el ancho y deja estirarse a la columna X
tabularx toma el ancho objetivo de la tabla como primer argumento y deja que las columnas X llenen lo que sobra: \begin{tabularx}{width}{column spec}. Una X es una columna p que absorbe automáticamente el ancho restante, y varias de ellas se lo reparten por igual. Si el desbordamiento viene de texto descriptivo largo, esta es la salida más corta: declara el ancho como \textwidth y, por construcción, la tabla no puede desbordarse. Es obra de David Carlisle, autor de longtable, y viene en el conjunto tools, así que no hay nada que instalar.
El mecanismo es algo inusual: tabularx encuentra los anchos componiendo la tabla varias veces. Primero da a cada X todo el ancho objetivo —con lo que la tabla queda demasiado ancha—, divide el exceso por el número de columnas X, estrecha cada una en esa cantidad y vuelve a componer, iterando hasta converger. Al final X se convierte en lo que defina \tabularxcolumn, cuyo valor por omisión es \newcommand{\tabularxcolumn}[1]{p{#1}}: una columna de párrafo alineada arriba. Redefínela con m{#1} para centrar verticalmente. Una celda X va justificada por omisión; para alinearla a la izquierda, antepón >{\raggedright\arraybackslash}X. La clave es \arraybackslash, que deshace la redefinición de \\ por parte de \raggedright y sus parientes. Si repites el mismo prefijo, \newcolumntype le da un alias de una letra y la especificación vuelve a ser legible.
\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}Dos advertencias. Primero, como el cuerpo se expande varias veces, los comandos con efectos secundarios —avanzar contadores, escribir archivos, \footnote, \verb— pueden comportarse mal dentro de tabularx. El arreglo habitual es envolver esa celda en una caja o una minipage. Segundo, el tabularx simple no tiene ponderación: X X reparte siempre a partes iguales, y para un 2:1 necesitas o bien el X[2] de tabularray de más abajo, o un p{} calculado a mano mediante \newcolumntype.
tabulary: repartir el ancho según el contenido de cada columna
Mientras tabularx reparte sus columnas X por igual, tabulary distribuye el ancho en proporción al ancho natural del contenido de cada columna. Cuando una columna lleva una etiqueta corta y otra una descripción larga, el reparto igualitario queda torpe. La sintaxis coincide: \begin{tabulary}{width}{column spec}, con cuatro tipos de columna: L izquierda, C centrada, R derecha, J justificada. Se pueden mezclar l, c, r y p{width} corrientes, pero quedan fuera de la medición y conservan su ancho natural. Cada columna medida se pondera por el ancho natural de su celda más ancha y se escala para que la tabla sume el ancho pedido, aunque una columna ya más estrecha que su parte se deja como está. Para que el reparto no se desmande, una columna medida queda acotada por \tymin (por omisión 10pt) y \tymax (por omisión 2\textwidth): la válvula de seguridad contra una entrada descomunal que monopolice la columna.
\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}Aquí ambas columnas son L y, sin embargo, «Term», de contenido corto, sale estrecha, y «Description», llena de prosa, se lleva la parte ancha. Con tabularx y X X serían idénticas, así que para una tabla de etiqueta más texto tabulary resulta más natural. Pero tabulary también procesa el cuerpo más de una vez, de modo que rigen las mismas precauciones con notas y contadores.
tabularray: el entorno tblr reúne ancho y reglas en una sola sintaxis
tabularray reduce a una sola interfaz clave-valor lo que antes exigía la cooperación de array, booktabs, multirow, colortbl y diagbox. Lo escribe Jianrui Lyu (lvjr), descarta la vieja maquinaria de \halign y analiza y compone tablas directamente con LaTeX3 (expl3). La copia incluida en TeX Live 2024 lleva fecha 2024-02-16, versión interna 2024A. El entorno principal es tblr; se carga con \usepackage{tabularray}.
La estructura de tblr difiere un poco de tabular: antes del cuerpo viene un argumento de opciones clave-valor separadas por comas, la especificación interna, como en \begin{tblr}{ … inner spec … }. La alineación de columnas se declara con la clave colspec. La forma familiar de una letra colspec={lcr} sigue valiendo, pero la fuerza real está en Q[…] (una columna genérica que recibe alineación, ancho y otras opciones entre corchetes) y X[…] (una columna expansible como en tabularx). X[c] es una columna expansible centrada; X[2,l] una alineada a la izquierda con coeficiente 2, el doble de ancha que una X normal. En el contexto del desbordamiento, lo que importa es que width= y colspec= viven entre las mismas llaves y que esos coeficientes permiten fijar la proporción. Medido, un tblr con width=\textwidth y colspec={X[2,l] X[1,r] X[1,r]} produjo una caja de exactamente 345,0pt, justo el ancho objetivo.
El ancho al que se expanden las columnas X lo da la clave width (\linewidth si no se fija). El espaciado entre filas y entre columnas se controla con rowsep y colsep, que en tblr valen por omisión rowsep=2pt y colsep=6pt. Las reglas son declarativas: hlines / vlines dibujan todas las reglas horizontales / verticales, y hline{n} / vline{n} dan estilo a una línea concreta, como hline{2}={1pt,solid} (Z es el índice especial de la última fila). No se escribe \hline en el cuerpo. Los ajustes recurrentes se sacan fuera con \SetTblrInner{rowsep=2pt}.
Las celdas combinadas se declaran en el cuerpo con \SetCell. \SetCell[c=2]{c} es una celda centrada que abarca 2 columnas (equivalente a \multicolumn), y \SetCell[r=2]{c} abarca 2 filas (equivalente a \multirow); c= y r= dan la extensión en columnas y filas, y el argumento entre llaves la alineación. Para dar estilo a filas o columnas enteras, usa \SetRow y \SetColumn: \SetRow{cyan8} sombrea una fila en cian pálido, con los nombres de color integrados en el paquete. Lo mismo puede declararse desde la especificación interna, como row{1}={font=\bfseries}, column{2}={halign=r}, cell{2}{3}={c=2}, lo que mantiene limpio el cuerpo.
\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}Este tblr fija el ancho de la tabla al ancho del texto con width=\textwidth. Las tres columnas son Q[l] (columna básica izquierda), X[c] (columna expansible centrada) y X[2,l] (columna expansible izquierda con coeficiente 2), así que las dos columnas X dividen el ancho sobrante 1 : 2 y la columna 3, “Description”, acaba siendo la más ancha. No aparece \hline en el cuerpo: las reglas vienen solo de las claves hline{…} de la especificación interna. La primera fila va en negrita con row{1}={font=\bfseries}, y la celda “Table environment” de la columna 1 abarca dos filas con \SetCell[r=2]{l}. Llegar hasta aquí sin cargar booktabs, multirow y array es precisamente el atractivo de tabularray.
Cuando la tabla es larga además de ancha, toman el relevo dos entornos derivados. longtblr es un tblr que abarca varias páginas, con filas de encabezado repetidas, leyendas y notas al pie; talltblr es una tabla de una sola página con notas debajo, al estilo de threeparttable. En ambos, la leyenda, la etiqueta, note{…} y similares van en el argumento opcional […] antes del cuerpo, la especificación externa. Repetir un encabezado en longtblr es simplemente rowhead=1 —un recuento llano de filas—, más escueto que los cuatro marcadores de longtable.
resizebox miente sobre el tamaño de tu letra
El \resizebox{\textwidth}{!}{...} de graphicx escala su contenido en bloque hasta el ancho indicado. Es la forma más rápida de meter una tabla en el papel y, de paso, encoge la letra en un factor que no aparece en ninguna parte del código fuente. Medido: al entregar la tabla de 404,83pt a \resizebox{\textwidth}{!} se obtiene una caja de 345,01pt de ancho y la altura baja de 26,07pt a 22,22pt. Ambas razones dan 0,8522. Así que la letra que crees de 10pt es de 8,52pt en la página. El documento dice \documentclass[10pt] y el papel dice 8,52pt: un accidente asegurado allí donde un revisor o unas normas de envío comprueben el cuerpo.
¿Por qué cabe con \resizebox y no con \scriptsize (cuerpo 7)? Por la misma razón que al principio de esta página: \resizebox encoge también el relleno entre columnas. Un cambio de cuerpo no quita ni un punto a esos 144pt, mientras que escalar por 0,8522 los deja en 122,7pt. Así es como un cuerpo aparente de 8,52pt con \resizebox gana a un 7pt real con \scriptsize. Dicho al revés, \resizebox fabrica una tabla cuyo relleno también ha sido apretado: doble desventaja para la legibilidad.
Y \resizebox esconde una trampa mucho más visible: dale una tabla pequeña y la agranda. Medido, una tabla diminuta de 4,44pt de ancho entregada a \resizebox{\textwidth}{!} salió con 345,46pt: un monstruo estirado unas setenta y ocho veces. Aplícalo por reflejo a todas las tablas, como se hace con \includegraphics, y las estrechas se hinchan. Aquí es donde adjustbox y su max width=\textwidth se ganan el sueldo: la misma tabla de 4,44pt se quedó en 4,44pt y solo la de 404,83pt bajó a 345,01pt. Reducir cuando haga falta y nunca agrandar: ese es el valor por omisión más seguro.
\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}Poner la página en horizontal: lscape, pdflscape y rotating
Solo pdflscape hace que la página gire de verdad en un visor de PDF. Los tres rotan el contenido noventa grados, mediante \begin{landscape} o sidewaystable, pero solo pdflscape escribe en el PDF la instrucción «muestra esta página girada», es decir, la entrada /Rotate 90. Aquí está el mismo documento compuesto de tres formas, comprobado con pdfinfo.
| Paquete | Entorno | Lo que pdfinfo informa de rot y el tamaño de página |
|---|---|---|
lscape | landscape | rot: 0 en todas las páginas, sigue 612 x 792. Solo el contenido |
pdflscape | landscape | rot: 90 solo en esa página, 612 x 792. El visor la gira |
rotating | sidewaystable | rot: 0, 612 x 792. Gira como flotante numerado |
Fíjate en que en los tres casos el tamaño de página sigue siendo 612 x 792: nada se ha puesto físicamente en horizontal, solo gira el contenido. De ahí sale la decisión. Para un PDF que se leerá en pantalla, usa pdflscape y ahórrale la tortícolis a quien lee; pdflscape carga lscape y añade el /Rotate, así que la sintaxis de lscape sigue valiendo. Para algo impreso y encuadernado, lscape basta: se gira el papel. Si la tabla debe seguir siendo un flotante numerado y con leyenda, usa sidewaystable de rotating (o sidewaysfigure para una figura). rotating ofrece además las opciones figuresright y figuresleft para elegir el sentido de giro.
\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}Dejar que la tabla se desborde hacia los márgenes con makebox
El bloque de texto mide 345pt, pero el papel da más de sí. Con los valores por omisión de article, el margen izquierdo mide 134,27pt y el derecho 135,03pt: 269pt de blanco vacío junto al texto. El modismo para meterse ahí es \noindent\makebox[\textwidth]{...}. \makebox mete su contenido en una caja de ancho \textwidth y, si el contenido es más ancho, se desborda por igual a ambos lados. Para la tabla de 404,83pt son 29,92pt hacia cada margen: la tabla se ensancha y el centro óptico de la página no se mueve.
Una cosa hay que aceptar: como el contenido excede la caja, TeX sigue informando Overfull \hbox. Es la única vez en que puedes ignorar ese aviso: el desbordamiento es deliberado. Para desbordar por un solo lado, \makebox[\textwidth][l]{...} fija el borde izquierdo y deja que la tabla corra hacia la derecha. Para algo más controlado, el entorno adjustwidth del paquete changepage ensancha el bloque de texto durante un tramo del documento, lo cual es más limpio y mantiene coherentes notas y titulillos. Recuerda que las cifras reales de los márgenes cambian con el papel y con los ajustes de geometry, así que comprueba el PDF real siempre que diseñes algo que invada el margen (cómo se fijan los márgenes corresponde a «Márgenes y caja de texto»).
Partir la tabla: cortarla por la mitad o transponerla
Hay respuestas que no necesitan ningún paquete. Corta las columnas en dos tablas y repite la columna clave en ambas: para una tabla de doce columnas, pon los nombres de región en la primera columna de cada mitad y reparte los años en 2–6 y 7–12. La vista nunca tiene que cruzar un corte y el cuerpo sigue siendo el del texto. Nada se escala y nada se gira, así que a menudo es el resultado más legible. El otro movimiento es transponer. Una tabla de doce años por cinco regiones se alarga a lo ancho; cinco regiones por doce años se alarga a lo alto, y una tabla alta es asunto de longtable.
Cuál elegir al final
La causa decide. Si lo que desborda es una columna de prosa, usa tabularx —el X[2] de tabularray cuando las columnas deban ir ponderadas, tabulary cuando el reparto deba seguir al contenido—; declarar el ancho sin más es el arreglo más limpio. Si es un bosque de columnas numéricas, empieza por \tabcolsep y luego pregúntate si hacen falta todas esas columnas a la vez. Si de verdad todas las columnas deben caber en una hoja, usa max width de adjustbox en lugar de \resizebox. Si es demasiado ancha incluso para eso, gira la página con pdflscape. Para una tabla que empiezas desde cero, ve a por tabularray: ancho, reglas, color y fusiones en una sola sintaxis. Si la tabla es larga además de ancha, pasa a longtblr o longtable. Elijas el camino que elijas, mira el PDF terminado y pregúntate si un dígito de 8,5pt sigue siendo legible.
| Paquete | Cómo se fija el ancho | Mejor para |
|---|---|---|
tabularx | Total fijo; columnas X reparten por igual | Columnas de prosa de igual ancho ajustadas |
tabulary | Total fijo; repartido por contenido | Tablas desiguales de etiqueta más texto |
tabularray | clave width más columnas X, con coeficientes | Tablas modernas que unifican reglas, color y combinaciones |
adjustbox | encoge solo si desborda (max width) | Poner un techo seguro a una tabla existente |
pdflscape | no toca el ancho y gira la página 90 grados | Tablas que nunca caben en vertical |
El detalle de las especificaciones de columnas en sí (\multicolumn, el >{…} del paquete array, etc.) corresponde a «Especificación de columnas, alineación y anchura», los fundamentos de combinar celdas a «Combinar celdas», y las tablas muy largas que abarcan páginas a la página «longtable».