Les listes LaTeX sont trop aérées : c'est en général pour cela qu'on se tourne vers le package enumitem, mais peu de gens ont regardé les chiffres. Dans la classe article, la distance de ligne de base entre deux éléments vaut 20pt, contre 12pt pour une ligne ordinaire : huit points d'air supplémentaires entre chaque paire d'éléments. Ces huit points sont deux longueurs, \itemsep (4pt) et \parsep (4pt), et le package enumitem existe pour les réécrire directement au moyen d'options clé=valeur comme itemsep=0pt. Cette page suit ce que valent réellement les réglages par défaut, ce que changent vraiment nosep et leftmargin=*, et comment \setlist fixe une politique pour tout un document — chiffres mesurés à l'appui.
Ce que valent réellement les réglages de liste de LaTeX
Mesuré dans article à 10pt, niveau 1 : \itemsep vaut 4pt, \parsep 4pt, \topsep 8pt, \leftmargin 25pt, \labelwidth 20pt et \labelsep 5pt. Ces chiffres rendent concret le reproche d'excès d'air. L'espace vertical inséré entre deux éléments est \itemsep plus \parsep, 8pt au total ; ajoutez l'interligne de 12pt et vous obtenez 20pt. Dans un texte composé sur une grille de 12pt, seule la liste avance donc à 1,67 ligne par élément. Typographiquement, c'est voulu : les entrées doivent se séparer visuellement. Mais dix entrées courtes à la suite laissent la page trouée. Horizontalement, même histoire : face à un \leftmargin de 25pt, la puce elle-même fait moins de 5pt de large ; 20pt de ce retrait ne sont que du vide.
| Longueur (= nom de clé) | Défaut de article (niveau 1) | Où elle agit |
|---|---|---|
itemsep | 4pt (plus 2pt minus 1pt) | Entre deux éléments |
parsep | 4pt (plus 2pt minus 1pt) | Entre paragraphes d'un même élément |
topsep | 8pt (plus 2pt minus 4pt) | Au-dessus et au-dessous de toute la liste |
partopsep | 2pt (plus 1pt minus 1pt) | En plus, seulement si la liste ouvre un nouveau paragraphe |
leftmargin | 25pt | Retrait de tout le bloc d'éléments depuis la gauche |
labelwidth | 20pt | Largeur de la boîte d'étiquette ; une étiquette plus large déborde à gauche |
labelsep | 5pt | Entre la boîte d'étiquette et le texte de l'élément |
rightmargin | 0pt | La marge de droite ; sert à resserrer la liste des deux côtés, comme pour une citation |
itemindent | 0pt | Retrait supplémentaire de la seule première ligne d'un élément ; une valeur négative la tire à gauche |
labelindent | — (clé ajoutée par enumitem) | De la marge extérieure au bord gauche de la boîte d'étiquette |
Les valeurs se réduisent avec la profondeur. Au niveau 2 de itemize, \itemsep et \parsep tombent à 2pt, \topsep à 4pt et \leftmargin à 22pt ; aux niveaux 3 et 4, \parsep atteint 0pt et \topsep 2pt, tandis que \leftmargin s'amincit à 18,7pt puis 17pt. LaTeX applique donc d'emblée une politique qui ouvre surtout les niveaux peu profonds ; les imbrications profondes sont déjà serrées. C'est pourquoi le niveau que l'on souhaite comprimer est presque toujours le niveau 1.
L'interface clé=valeur : les clés sont les longueurs mêmes de LaTeX
Chargé dans le préambule par \usepackage{enumitem}, il donne aux trois environnements itemize, enumerate et description un argument optionnel : des paires clé=valeur séparées par des virgules entre crochets configurent cette liste-là. L'idée maîtresse est que les noms de clés sont exactement les noms de longueur du tableau ci-dessus. itemsep=1ex réécrit \itemsep ; leftmargin=1cm réécrit \leftmargin. Apprendre enumitem revient donc à apprendre les rouages internes des listes de LaTeX — c'est là son véritable avantage sur l'ancienne habitude consistant à redéfinir les commandes internes par \renewcommand. TeX Live 2024 fournit la version v3.9 (2019/06/20) de Javier Bezos ; kpsewhich enumitem.sty indique la copie utilisée par votre installation.
\usepackage{enumitem}
% ...
\begin{itemize}[itemsep=1ex, leftmargin=1cm]
\item the key names are the LaTeX length names
\item second entry
\end{itemize}Une même clé peut être redéfinie à trois niveaux : le document entier, un type d'environnement, ou une liste isolée (via \setlist, plus bas). La valeur la plus spécifique l'emporte ; le plus propre est donc de fixer d'abord une politique globale et de n'y déroger que là où il le faut. Si une valeur est entièrement entourée d'accolades, une paire extérieure est retirée (comportement par défaut de keyval) : doublez-les pour conserver les accolades elles-mêmes.
Resserrer une liste : nosep contre noitemsep
nosep met quatre longueurs verticales à zéro ; noitemsep n'en met que deux. Dans le source du package, nosep fixe \partopsep, \topsep, \itemsep et \parsep tous à 0pt, tandis que noitemsep ne touche que \itemsep et \parsep. Celle qu'on oublie est partopsep : les 2pt ajoutés uniquement lorsque la liste commence après une ligne blanche, donc comme un nouveau paragraphe. À la mesure, un itemize en nosep place ses lignes de base d'élément exactement à 12pt — l'espacement même des lignes de texte ordinaires. L'espace au-dessus et au-dessous disparaît aussi, si bien que la liste se fond entièrement dans la prose.
% nosep -> partopsep = topsep = itemsep = parsep = 0pt
% noitemsep -> itemsep = parsep = 0pt, list keeps its 8pt topsep
\begin{itemize}[nosep]
\item item baselines land exactly 12pt apart
\item as tight as ordinary body text
\end{itemize}Le choix dépend de la question de savoir si la liste doit se lire comme une partie du texte courant. Quand les entrées sont l'essentiel — une marche à suivre, une diapositive — nosep convient. Pour une liste courte insérée dans le corps d'un article, noitemsep est plus sûr : les 8pt au-dessus et au-dessous subsistent, et la frontière entre paragraphe et liste reste visible. Si l'on resserre aussi le haut et le bas, la liste se colle aux paragraphes voisins et l'on distingue mal où l'énumération commence et finit. Il existe par ailleurs une clé plus ancienne, nolistsep, qui ne diffère de nosep que par un topsep fixé à 0pt plus .1pt au lieu d'un zéro net ; pour un document neuf, préférez nosep.
label= et ref= : styler l'étiquette et le renvoi séparément
L'étiquette d'une liste se règle avec label=. Dans la valeur, les formes étoilées \arabic*, \alph*, \Alph*, \roman* et \Roman* représentent le compteur courant de ce niveau. label=(\arabic*) donne (1) (2) (3), label=\alph*) donne a) b) c), et label=\Roman*. donne I. II. III. Les formes étoilées ne prennent pas d'argument ; voyez-les comme des graphies spéciales qui n'ont de sens qu'à l'intérieur d'une étiquette. Il existe aussi label*=, qui se greffe sur l'étiquette parente : l'imbrication accumule alors 1., 1.1., 1.2., et ainsi de suite.
\begin{enumerate}[label=(\arabic*), ref=\arabic*]
\item \label{step:one} prepare the ingredients
\item heat the pan
\end{enumerate}
Go back to step~\ref{step:one}. % prints "step 1", not "step (1)"Par défaut, label= gouverne aussi l'aspect du renvoi. Placez un \label sur un élément d'une liste déclarée simplement [label=(\arabic*)] : \ref imprime le (1) entre parenthèses — d'où l'agacement quotidien du « revenir à l'étape (1) » aux parenthèses doublées. Ajoutez ref=\arabic* et l'étiquette imprimée reste (1) tandis que \ref renvoie un 1 nu. La compilation du code ci-dessus le confirme exactement. À noter : les valeurs de label et ref sont traitées comme des arguments mobiles, si bien qu'une commande fragile qui s'y trouve peut réclamer \protect ; les formes étoilées des compteurs, elles, ne posent pas de problème.
Pour écrire les étiquettes dans la graphie brève de l'ancien package enumerate, chargez-le par \usepackage[shortlabels]{enumitem}. Un A, a, I, i ou 1 en premier élément entre crochets vaut alors respectivement \Alph*, \alph*, \Roman*, \roman* ou \arabic*, et \begin{enumerate}[(1)] fonctionne. Commode pour migrer un vieux manuscrit hors du package enumerate ; dans un travail neuf, un label= explicite énonce mieux l'intention lorsqu'on y revient.
leftmargin=* et wide : laisser la marge se calculer
Les clés horizontales ne sont pas indépendantes : une seule équation les relie, \leftmargin + \itemindent = \labelindent + \labelwidth + \labelsep. Donnez * à certaines au lieu d'une valeur et enumitem résout l'équation pour les autres. À la mesure, l'effet est spectaculaire : un itemize par défaut a \leftmargin à 25pt ; avec [leftmargin=*], il tombe à 9,99pt — juste de quoi loger la puce. Le cas inverse importe davantage : avec une étiquette large comme label=(\roman*), « (viii) » n'entre pas dans la boîte de 20pt par défaut et déborde à gauche, alors que leftmargin=* élargit la boîte à la mesure de l'étiquette. Dès que vous employez une étiquette large, écrivez leftmargin=* avec elle : vous éviterez la plupart des accidents.
L'autre clé commode est wide. Elle annule la marge gauche et la boîte d'étiquette, si bien que l'étiquette se lit comme une partie du texte et que l'élément se compose en paragraphe ordinaire. Dans le source, elle met \leftmargin et \labelwidth à zéro, place son argument (par défaut \parindent) dans \labelindent, aligne \listparindent dessus et calcule \itemindent par l'équation. À la mesure, \leftmargin vaut 0pt, \itemindent 20pt et \listparindent 15pt, soit \parindent. Passez une valeur, comme wide=0pt, pour changer le retrait. C'est la clé à choisir quand la maquette veut des listes qui ne débordent pas à gauche et un bloc de texte au bord gauche unique. À retenir avec elle, align= décide si l'étiquette est cadrée à gauche (left), à droite (right, valeur par défaut) ou placée dans une parbox alignée à gauche (parleft).
Commencer à 5, ou reprendre la liste précédente (start, resume, series)
start= fixe le numéro du premier élément et resume poursuit la numérotation du enumerate immédiatement précédent. Couper une procédure par un paragraphe explicatif puis reprendre à « 7. » est un besoin très fréquent, et le faire à la main avec \setcounter casse dès qu'on insère une étape de plus. Composé pour de bon, [start=5] a donné 5 et 6 ; après un paragraphe intercalé, [resume] a bien repris à 7. Avec resume*, on hérite non seulement du numéro mais aussi des options de la liste précédente (cette forme étoilée n'a de sens qu'entre les crochets de l'environnement).
\begin{enumerate}[start=5]
\item numbered 5
\item numbered 6
\end{enumerate}
An explanatory paragraph goes here.
\begin{enumerate}[resume]
\item numbered 7 -- the count carries over
\end{enumerate}resume ne regarde que la liste immédiatement précédente ; il ne suffit donc pas lorsque plusieurs listes très éloignées — d'une section à l'autre, par exemple — doivent porter un seul comptage continu. Pour cela, utilisez une série : marquez la première liste par series=nom, puis écrivez resume=nom ou resume*=nom sur les suivantes, et la numérotation se raccorde quoi qu'il y ait entre les deux. Pour une longue procédure répartie sur plusieurs sections, c'est la seule méthode qui tienne vraiment.
Des réglages pour tout le document avec \setlist, et sa propre liste avec \newlist
Écrire les mêmes options à chaque fois n'est pas réaliste. \setlist applique des réglages en bloc à un type et à un niveau de liste choisis : \setlist{...} sans crochets atteint tous les niveaux de toutes les listes, \setlist[itemize]{...} tous les niveaux de itemize, et \setlist[enumerate,1]{...} le seul niveau 1 de enumerate. Le \setlist* étoilé s'ajoute aux réglages déjà posés au lieu de les remplacer. Pour corriger dans tout un document l'excès d'air décrit en tête de page, une ligne de \setlist{noitemsep} dans le préambule est le changement au meilleur rapport effet/effort.
\usepackage{enumitem}
\setlist{noitemsep} % tighten every list in the document
\setlist[itemize]{leftmargin=*} % let itemize size its own margin
\setlist[enumerate,1]{label=(\arabic*), ref=\arabic*}
% a list type of your own
\newlist{steps}{enumerate}{1}
\setlist[steps]{label=\textbf{Step \arabic*.}, leftmargin=*}Un cran plus loin, vous pouvez définir votre propre type de liste. \newlist{nom}{type}{profondeur max} clone l'une des trois listes de base (enumerate, itemize ou description) dans un nouvel environnement, et un \setlist[nom]{...} qui suit lui donne son allure (il faut au minimum régler l'étiquette). En composant le code ci-dessus, \begin{steps} a produit « Step 1. » et « Step 2. ». Le gain tient moins au rendu qu'à la lisibilité du source : voir \begin{steps} dit au lecteur qu'il s'agit d'une procédure, sans regarder la page. Le sens de la liste est porté par son nom plutôt que par sa mise en forme.
Listes en ligne dans un paragraphe (enumerate*)
Chargez le package par \usepackage[inline]{enumitem} et vous gagnez les environnements étoilés enumerate*, itemize* et description*, dont les entrées défilent horizontalement dans le paragraphe au lieu de passer à la ligne. Composé, cela tient sur une seule ligne : « We need (1) flour (2) sugar (3) salt for this. » Lorsqu'il s'agit simplement de dénombrer trois ou quatre courtes expressions, c'est souvent plus lisible que de consacrer quatre lignes de page à une liste hors texte — et dans la prose savante, énumérer ainsi des conditions est plutôt le style standard.
\usepackage[inline]{enumitem}
% ...
We need
\begin{enumerate*}[label=(\arabic*)]
\item flour \item sugar \item salt
\end{enumerate*}
for this.Les séparateurs se règlent avec itemjoin (entre les éléments ; une espace par défaut), itemjoin* (pour un séparateur différent juste avant le dernier élément — c'est ainsi qu'on obtient l'anglais « a, b, and c ») et afterlabel (juste après l'étiquette ; ~ par défaut). Attention : les éléments d'une liste en ligne sont encadrés par défaut, si bien que flottants, listes imbriquées et équations hors texte ne peuvent y figurer ; indiquez mode=unboxed si vous en avez besoin. En pratique, la limite raisonnable est celle-ci : les listes en ligne servent uniquement à de courtes expressions.