Placement et mise en forme des tableaux

Ce n’est pas une impression : la légende d’un tableau semble collée au tableau. Les classes standard de LaTeX fixent \abovecaptionskip à 10pt et \belowcaptionskip à 0pt — identiquement dans article, report et book — et ces valeurs sont réglées pour les figures. Comme l’usage place la légende d’un tableau au-dessus de celui-ci, le côté aéré se retrouve en haut et le côté nul touche le tableau. Voilà d’où vient cette impression d’étroitesse. Cette page traite de tout ce qui entoure le tabular : placement et légende via l’environnement table, que faire d’un tableau plus large que la page, comment le tourner en paysage, et threeparttable pour les notes. La construction du contenu lui-même relève de « Bases de tabular » et de « Spécification des colonnes, alignement et largeur ».

Pourquoi les tableaux flottent — table contre tabular

Parce qu’un tableau ne peut pas être coupé par un saut de page. Ce que construit tabular est une grande boîte, et une boîte ne se scinde pas à une frontière de page. Si LaTeX tentait de la composer exactement à l’endroit de la source alors que l’espace restant est insuffisant, on obtiendrait un blanc ou une page saccagée. Il traite donc tableaux et figures comme des flottants : il les détache du texte courant et les envoie là où ils tiennent. L’outil pour cela est l’environnement table : on y place un tabular, on lui donne un titre numéroté comme « Tableau 1 » avec \caption{…}, et on le rend référençable par \label{…} et \ref{…}. Dans le texte, on écrit alors une référence par numéro — « comme le montre le tableau~\ref{tab:sales} » — et quel que soit le nombre de pages parcourues par le tableau, le numéro reste juste. Le ~ est une espace insécable qui empêche le mot et son numéro d’être séparés par un saut de ligne.

document.tex
\usepackage{booktabs}
\usepackage{float}   % needed only for the [H] specifier

\begin{table}[htbp]
  \centering
  \caption{Quarterly sales}
  \label{tab:sales}          % \label always AFTER \caption
  \begin{tabular}{@{}lrr@{}}
    \toprule
    Quarter & Sales & YoY \\
    \midrule
    Q1 & 1{,}200 & +5\% \\
    Q2 & 1{,}350 & +8\% \\
    \bottomrule
  \end{tabular}
\end{table}

% in the body: as Table~\ref{tab:sales} shows ...

La différence entre les spécificateurs [htbp] et [H]

[htbp] est un ensemble d’emplacements autorisés ; [H] est l’ordre de cesser de flotter. Dans les crochets qui suivent \begin{table}, on énumère h (ici), t (haut de page), b (bas de page) et p (page réservée aux flottants). Sans rien écrire, la valeur par défaut, en article comme en book, est tbp : h n’est même pas candidat au départ. Le point important : l’ordre d’écriture ne change pas l’ordre des essais. LaTeX tente toujours t, puis b, puis p ; [htbp] et [bpht] se comportent donc de façon identique. Voyez les crochets non comme une préférence, mais comme une énumération d’autorisations.

Un ! initial, comme dans [!ht], signifie « pour ce flottant seulement, ignorer les limites internes et tenter le placement » — cela ne veut pas dire « mets-le ici ». Ces limites internes sont des nombres bien réels : en article, les valeurs par défaut sont \topfraction = 0,7 (part de page que les flottants peuvent occuper en haut), \bottomfraction = 0,3, \textfraction = 0,2 (part minimale que doit garder le texte), \floatpagefraction = 0,5 (seuil de création d’une page de flottants), et au plus deux flottants en haut, un en bas et trois au total par page (\topnumber, \bottomnumber, \totalnumber). Si un tableau refuse d’apparaître, c’est généralement l’une de ces limites, et ! ne fait qu’assouplir le test. Pour le fixer vraiment, utilisez [H] du package float : avec \usepackage{float}, \begin{table}[H] empêche le tableau de flotter et le compose exactement à l’endroit de la source, au risque d’un grand blanc en bas de page. Lire H comme « un flottant qui ne flotte pas » évite bien des surprises.

SpécificateurSensValeur par défaut associée
hIci, à la position de la source. h seul est interdit ; t est ajoutéAbsent de la valeur par défaut tbp
tHaut d’une page de texte\topfraction = 0,7, \topnumber = 2
bBas d’une page de texte\bottomfraction = 0,3, \bottomnumber = 1
pPage réservée aux flottants, sans texte courant\floatpagefraction = 0,5
!Pour ce flottant seulement, ignorer les fractions et comptes ci-dessus. Pas une positionConcerne aussi \textfraction = 0,2 et \totalnumber = 3
HCesser de flotter et fixer sur place. Nécessite le package floatN’existe pas en LaTeX standard

Légende au-dessus du tableau, sous la figure — et \label après \caption

Ces deux points expliquent l’essentiel des mésaventures de légende. \caption{…} donne au flottant un titre numéroté, « Tableau 1: » en article, « Tableau 1.1: » en book. Tableaux et figures ont des compteurs distincts, leurs numéros ne se mélangent donc jamais. Avec l’argument optionnel, \caption[court]{légende complète}, la liste des tableaux affiche la forme courte et le corps la forme complète. Et puisque c’est \caption qui incrémente le compteur, \label doit venir après \caption ; dans l’ordre inverse, \ref pointe sur le numéro précédent, en silence, sans la moindre erreur. Quant au placement, l’usage met la légende au-dessus d’un tableau et au-dessous d’une figure : on lit l’intitulé d’un tableau avant d’entrer dans les données, mais on regarde une figure avant d’en lire l’explication. Dans LaTeX, la légende est au-dessus si \caption précède le tabular, au-dessous s’il le suit.

C’est ici que la mesure de l’introduction porte ses fruits. Dans les classes standard, \abovecaptionskip vaut 10pt et \belowcaptionskip 0pt : l’air se trouve donc uniquement à l’extérieur de la légende, et rien ne sépare la légende du corps du flottant. Pour une figure, dont la légende est en dessous, cela convient ; pour un tableau, dont la légende est au-dessus, la légende touche le tableau. Deux remèdes. En LaTeX pur, déclarez \setlength{\belowcaptionskip}{6pt}. Avec le package caption, écrivez \usepackage[skip=6pt]{caption}, ou limitez-le aux tableaux par \captionsetup[table]{skip=6pt}. La mise en forme de la légende elle-même — police, séparateur, largeur — relève aussi du package caption, détaillé sur la page « Légendes et sous-figures ».

Pour centrer le contenu, on utilise \centering. Dans un flottant, l’idiome est \centering et non l’environnement center (\begin{center}…\end{center}) : center ajoute de l’espace vertical au-dessus et au-dessous, tandis que \centering n’est qu’une déclaration et n’ajoute rien. Pour pousser le tableau contre la marge de droite au lieu de le centrer, placez \hfill avant le contenu : tout le mou horizontal se rassemble alors à gauche. À noter : \centering dans un flottant est sans danger, mais \centering dans une colonne p{largeur} est une autre affaire — si cette colonne est la dernière du tableau, le terminateur de rangée \\ se casse et l’on obtient ! Extra alignment tab has been changed to \cr. Le traitement d’un \centering écrit dans une spécification de colonnes relève de « Spécification des colonnes, alignement et largeur ».

Quand un tableau LaTeX dépasse la largeur du texte

Avant de réduire quoi que ce soit, mesurez où passe la largeur. Les colonnes de type l, c et r ne se replient pas : un tableau à nombreuses colonnes déborde donc de \textwidth. Mais le débordement n’est généralement pas fait de lettres — c’est l’espace entre les colonnes. Un cas réel : un tableau booktabs de douze colonnes, une rangée d’en-tête et une de données, mesure 412,95pt de large, alors que \textwidth vaut 345pt dans l’article par défaut : 68pt de dépassement. Composez le même tableau avec \tabcolsep = 0pt et il tombe à 268,95pt — un écart de exactement 144pt, soit 2 × 12 colonnes × 6pt. Autrement dit, 35 % de la largeur du tableau étaient du blanc, pas du texte.

Cette connaissance change l’ordre des remèdes. Le conseil habituel — descendre d’un corps — donne 392,77pt en \small et 372,55pt en \footnotesize pour le même tableau ; ni l’un ni l’autre n’atteint 345pt. La raison : \tabcolsep est une longueur, elle ne se met pas à l’échelle avec la police, si bien que les 144pt de blanc survivent intacts à la réduction du corps. Réduisez-la de moitié avec \setlength{\tabcolsep}{3pt} et le tableau tombe à 340,95pt : il tient, au corps du texte. \small combiné à \tabcolsep = 4pt donne 344,77pt. Procédez dans cet ordre : le blanc d’abord, la taille de police ensuite, la mise à l’échelle en dernier.

latex
\usepackage{graphicx}   % for \resizebox

% 1. trim the padding first -- \tabcolsep is 6pt on EACH side of EVERY column
\begingroup
\setlength{\tabcolsep}{3pt}
\begin{tabular}{@{}lrrrrrrrrrrr@{}}  % @{} also removes the outer 2 x 6pt
  ...
\end{tabular}
\endgroup

% 2. only then consider a smaller size, or scaling as a last resort
\resizebox{\textwidth}{!}{%
  \begin{tabular}{lrrrrr}
    ...
  \end{tabular}%
}

Placer @{} aux deux extrémités de la spécification de colonnes supprime également le \tabcolsep extérieur et aligne le tableau sur le bord gauche du texte — mesuré, exactement 2 × 6pt = 12pt. C’est l’idiome familier des tableaux booktabs. Si rien de tout cela ne suffit, le dernier recours est \resizebox{largeur}{hauteur}{matériel} de graphicx, où mettre ! à l’une des deux valeurs met à l’échelle proportionnellement. Mais cela met le contenu à l’échelle : passez le tableau précédent dans \resizebox{\textwidth}{!} et le facteur vaut 345 ÷ 412,95 = 0,836 ; le corps 10pt sort à environ 8,4pt et le \toprule de 0,8pt à 0,67pt. Ni les lettres ni les filets ne s’accordent plus au texte voisin : traitez cela comme un dépannage. À la place de \resizebox, adjustbox propose une forme d’environnement, \begin{adjustbox}{width=\textwidth}…\end{adjustbox}. Pour aérer un peu les rangées, \renewcommand{\arraystretch}{1.2} (le défaut est 1) rend un tableau de trois rangées plus haut de 0,2 × 3 × 12pt = 7,2pt dans un document en 10pt.

Si rien de cela ne tient, c’est le signal de changer d’outil. La colonne X de tabularx, qui étire les colonnes jusqu’à une largeur cible, et le tblr de tabularray sont traités sur la page « Environnements de tableaux avancés ». Si le problème vient de trop de rangées pour une page, il s’agit de longueur et non de largeur, et la réponse est longtable, qui sait franchir les sauts de page — page « Tableaux sur plusieurs pages ». Les deux méritent d’être envisagés avant la mise à l’échelle et la rotation de cette page.

Mettre un tableau en paysage — sidewaystable et rotatebox

Un tableau trop grand pour une page en portrait peut occuper une page entière en tournant de 90° : placez-le dans l’environnement sidewaystable du package rotating au lieu de table. La légende et le numéro tournent avec lui, et il figure toujours dans la liste des tableaux. En recto verso, le package choisit automatiquement le sens de rotation pour que la double page se lise naturellement. Pour les figures, l’équivalent est sidewaysfigure. Pour ne faire pivoter qu’une partie d’un tableau, selon un angle quelconque, utilisez \rotatebox{angle}{matériel}, également fourni par graphicx/rotating ; l’usage typique est de dresser une cellule d’en-tête avec \rotatebox{90}{long column name} (les angles positifs tournent dans le sens antihoraire).

document.tex
\usepackage{rotating}
\usepackage{booktabs}

\begin{sidewaystable}
  \centering
  \caption{A wide table turned 90 degrees}
  \label{tab:wide}
  \begin{tabular}{@{}lrrrrrrrr@{}}
    \toprule
    Region & Q1 & Q2 & Q3 & Q4 & Total & Prev & Diff & Ratio \\
    \midrule
    East & 120 & 135 & 128 & 142 & 525 & 500 & +25 & 105\% \\
    \bottomrule
  \end{tabular}
\end{sidewaystable}

Une limite est à connaître : rotating manipule des boîtes tournées, et une boîte tient toujours sur une seule page. Il ne peut donc pas produire de texte courant en paysage sur plusieurs pages. Dans ce cas, utilisez lscape, qui compose le texte de côté, ou pdflscape, qui fait pivoter la page PDF elle-même. pdflscape convient particulièrement aux documents lus à l’écran, puisque le lecteur tourne la page pour vous. Un tableau à la fois en paysage et sur plusieurs pages demande de combiner pdflscape et longtable.

Des notes sous un tableau — threeparttable

Employez \footnote dans un tabular et la note part en bas de page ou ne s’imprime pas du tout. Le package threeparttable de Donald Arseneau résout ce problème. Comme son nom l’indique, il traite un tableau en trois parties : titre (légende), corps (tabular) et notes (tablenotes) — et compose les notes à la largeur du tableau, juste au-dessous. Comme le précise la documentation du package, un threeparttable ne flotte pas de lui-même ; pour obtenir numéro et placement, on enveloppe le tout dans un table (ou table* pour la pleine largeur en composition à deux colonnes).

document.tex
\usepackage{booktabs}
\usepackage{threeparttable}

\begin{table}[htbp]
  \centering
  \begin{threeparttable}
    \caption{Yield by variety}
    \label{tab:yield}
    \begin{tabular}{@{}lrr@{}}
      \toprule
      Variety & Yield\tnote{a} & Price\tnote{b} \\
      \midrule
      Koshihikari & 540 & 380 \\
      Akitakomachi & 520 & 360 \\
      \bottomrule
    \end{tabular}
    \begin{tablenotes}
      \footnotesize
      \item[a] Kilograms per 10 a.
      \item[b] Wholesale price per kilogram.
    \end{tablenotes}
  \end{threeparttable}
\end{table}

Dans un environnement threeparttable, on place simplement, dans l’ordre, \caption, le tabular, puis tablenotes. La liaison des notes est manuelle : un marqueur tel que \tnote{a} dans une cellule, et la note écrite avec la même lettre en \item[a] … dans tablenotes. L’auteur a laissé sa raison de ne pas l’automatiser en tête du fichier .sty : « Pour l’instant, il n’y a rien d’automatique dans les notes… J’ai choisi cette méthode parce qu’une numérotation automatique par \footnote serait très difficile à utiliser, surtout parce que beaucoup de tableaux renvoient plusieurs fois à une même note. Si quelqu’un dispose d’un système automatique commode et élégant, je suis preneur ! » Le package est encore distribué avec cette conception intacte.

OptionEffet
paraCompose plusieurs notes à la suite dans un seul paragraphe, sans retour à la ligne
flushleftSupprime le retrait suspendu des notes
onlineImprime la marque \item en taille normale au lieu d’un exposant
normalRétablit la mise en forme par défaut, annulant une option globale pour un tableau

Ces options se fixent pour tout le document, comme dans \usepackage[para]{threeparttable}, ou pour un tableau donné, comme dans \begin{tablenotes}[flushleft]. threeparttable ne met pas la légende en forme lui-même : associez-le au package caption pour un véritable aspect de titre. Pour des notes sur un tableau qui s’étend sur plusieurs pages (longtable), utilisez le package frère threeparttablex.

  • Le tableau ne va pas où vous voulez — reconsidérez d’abord les lettres de [htbp] comme un ensemble d’autorisations, non comme un ordre. S’il ne bouge toujours pas, il bute sur \topfraction et consorts : essayez [!ht] ; pour le fixer vraiment, [H] de float.
  • La légende colle au tableau\belowcaptionskip vaut 0pt par défaut. Utilisez \setlength{\belowcaptionskip}{6pt} ou le skip= du package caption.
  • Le tableau dépasse la largeur de la page\tabcolsep et @{} d’abord, puis \small, \resizebox en dernier. Si les colonnes peuvent se replier, p{largeur} ou tabularx.
  • Trop de rangées — c’est une question de longueur, pas de largeur : longtable ; combinez-le à pdflscape s’il faut aussi le paysage.
  • Vous voulez une note sur une cellule — non pas \footnote, mais \tnote et tablenotes de threeparttable.