La puce que itemize place en tête de ligne dans LaTeX se penchait autrefois dès qu’elle tombait dans un passage en italique : le marqueur héritait tout simplement de la fonte en vigueur autour de lui. La version du 2020-02-02 a introduit une commande nommée \labelitemfont et a mis fin à ce travers. Le point d’une liste à puces n’est donc pas un ornement mais un caractère composé comme les autres. Cette page aborde itemize sous trois angles : où ces marqueurs sont réellement définis, ce qui se produit lorsqu’on en remplace un par \item[...], et quelles deux longueurs décident de l’espace entre les entrées.
Où la puce est définie : de \labelitemi à \labelitemiv
Les marqueurs ne résident pas du tout dans l’environnement itemize : ils résident dans la classe de document. En ouvrant article.cls, on trouve quatre commandes alignées, de \labelitemi à \labelitemiv, contenant dans l’ordre \textbullet (•), un \textendash gras (–), \textasteriskcentered (*) et \textperiodcentered (·). Le seul travail de itemize consiste à compter la profondeur courante, à composer le nom \labelitem suivi d’un chiffre romain, puis à appeler ce que ce nom contient. Changer un marqueur ne demande donc jamais de toucher à l’environnement : on remplace la commande. Et s’il n’y a rien après le quatrième niveau, la raison est tout aussi simple : aucun cinquième nom n’a jamais été défini.
| Commande | Niveau | Marqueur | Contenu dans article.cls |
|---|---|---|---|
\labelitemi | 1 | • | \labelitemfont \textbullet |
\labelitemii | 2 | – | \labelitemfont \bfseries \textendash (gras) |
\labelitemiii | 3 | * | \labelitemfont \textasteriskcentered |
\labelitemiv | 4 | · | \labelitemfont \textperiodcentered |
\labelitemfont | — | — | \normalfont ; isole le marqueur de la fonte environnante |
La dernière ligne, \labelitemfont, correspond au correctif de 2020 évoqué en tête. Les quatre marqueurs sont appelés avec elle en préfixe : une liste placée dans un bloc en italique ou en gras conserve désormais un marqueur droit. On peut aussi en tirer parti pour composer les marqueurs dans une tout autre fonte : \renewcommand{\labelitemfont}{\normalfont\sffamily} laisse le texte en romain à empattements et sort les marqueurs en linéale. Pour remplacer le marqueur de tout un niveau, on redéfinit le \labelitem… correspondant avec \renewcommand. Placé dans le préambule, il agit sur tout le document ; placé dans un environnement ou un groupe, seulement à cet endroit.
% swap the first-level marker for the whole document
\renewcommand{\labelitemi}{$\diamond$}
\begin{itemize}
\item this level now uses a diamond
\item so does this one
\end{itemize}Remplacer le marqueur d’une seule entrée avec \item[...]
Si l’on donne à \item un argument entre crochets, cette entrée seule reçoit le contenu des crochets comme marqueur. \item[$\star$] donne une étoile, \item[--] un tiret, \item[Note] le mot « Note » composé à la place de la puce. Une idée reçue très répandue mérite d’être corrigée ici : une étiquette entre crochets dans itemize n’est pas mise en gras. Le gras vient de l’environnement description, dont le \descriptionlabel contient bien un \bfseries. Le formateur d’étiquette de itemize se réduit à \hss\llap{…} : il aligne à droite et ne touche pas à la fonte.
\begin{itemize}
\item the default marker
\item[$\star$] a star for this one entry
\item[Note] a whole word in the marker slot
\end{itemize}Ce \llap crée aussi un piège. L’étiquette est composée en drapeau droit dans une boîte de largeur \labelwidth, et \llap déborde silencieusement. \item[Note] tient sans peine, mais un mot long comme \item[Prerequisite] s’étire vers la gauche au-delà du bloc de texte et, au pire, hors de la zone imprimée. L’interlignage reste intact et aucun avertissement Overfull \hbox n’apparaît : rien ne prévient avant l’examen du PDF. Si des mots doivent servir d’étiquettes, c’est le travail de description et non de itemize ; avec enumitem, labelwidth= et leftmargin= permettent de réserver la place.
Quand les entrées sont trop espacées : \itemsep et \parsep
L’espace entre deux entrées n’est pas une longueur mais la somme de deux. Avant d’entamer l’entrée suivante, \item insère \itemsep ; immédiatement après, un nouveau paragraphe commence et apporte en plus \parskip — or, dans une liste, \parskip a été fixé à \parsep. L’espace réel vaut donc \itemsep + \parsep. Dans un article en 10pt, les deux valent 4pt au niveau 1, soit 8pt au total ; face à un interlignage de 12pt, cela fait deux tiers de ligne d’air entre les entrées. C’est en général ce que l’on voit lorsqu’une liste « paraît distendue », et c’est pourquoi mettre le seul \itemsep à zéro ne resserre que la moitié.
| Longueur | Valeur par défaut au niveau 1 (article 10pt) | Ce qu’elle règle |
|---|---|---|
\itemsep | 4pt plus 2pt minus 1pt | l’espace que \item ajoute avant l’entrée suivante |
\parsep | 4pt plus 2pt minus 1pt | entre les paragraphes d’une entrée ; devient aussi \parskip, donc s’ajoute entre les entrées |
\topsep | 8pt plus 2pt minus 4pt | l’espace au-dessus et au-dessous de la liste entière |
\partopsep | 2pt plus 1pt minus 1pt | ajouté à \topsep uniquement si une ligne vide précède la liste |
La dernière ligne décrit un comportement sur lequel tout le monde trébuche au moins une fois. Laisser ou non une ligne vide avant \begin{itemize} fait passer l’espace au-dessus de la liste de 8pt à 10pt : une ligne vide fait démarrer la liste en mode vertical, et c’est précisément là que \partopsep s’ajoute. Reformater un fichier source et constater que la mise en page a bougé vient très souvent de là. Les valeurs elles-mêmes réservent une surprise : ce sont des longueurs élastiques avec des composantes plus et minus, qui peuvent se comprimer à 6pt ou s’étirer à 12pt lors de la mise en pages. Les chiffres écrits ne se retrouvent pas tels quels sur le papier. Les niveaux profonds sont en outre resserrés automatiquement : au niveau 2, \itemsep et \parsep valent 2pt chacun, au niveau 3 \parsep tombe à 0pt. Si les listes imbriquées paraissent plus compactes, c’est voulu.
% tighten one list by hand: inside the body it is \parskip,
% not \parsep, that still carries the second half of the gap
\begin{itemize}
\setlength{\itemsep}{0pt}
\setlength{\parskip}{0pt}
\item first
\item second
\item third
\end{itemize}Remarquez que c’est \parskip qui est mis à zéro, et non \parsep. La copie de \parsep vers \parskip a déjà eu lieu quand \begin{itemize} rend la main : modifier \parsep une fois dans le corps laisse en place les seconds 4pt. Mesuré sur la page, l’écart par défaut de 19,93pt d’une entrée à la suivante ne descend qu’à 15,94pt si l’on annule \parsep, et n’atteint 11,96pt — exactement une ligne — que lorsque \parskip passe à zéro. Plutôt que de répéter cela à chaque fois, mieux vaut charger enumitem et passer [noitemsep] (met \itemsep et \parsep à zéro) ou [nosep] (qui y ajoute \topsep et \partopsep) ; \setlist en fait ensuite le réglage par défaut du document. Une plainte voisine concerne les listes qui se coupent au mauvais endroit d’une page. C’est un choix, pas un accident : la classe article fixe \@itempenalty à −51. Une pénalité négative ne dit pas « une coupure est permise ici » mais « une coupure est souhaitée ici » : LaTeX traite donc activement la jointure entre deux entrées comme une bonne fin de page. Une liste qui ne doit pas être coupée doit être retenue explicitement, dans une minipage ou avec \samepage.
Les deux erreurs liées à \item
Un itemize ne peut pas être vide. Si \begin{itemize} … \end{itemize} se referme sans un seul \item, la compilation s’arrête sur ! LaTeX Error: Something's wrong--perhaps a missing \item. En pratique, le message vient moins d’un \item oublié que d’un texte ou une image posés tout en haut de la liste. La position juste après l’ouverture est réservée : seul un \item, ou un réglage d’espaces et de longueurs, y a sa place. L’erreur symétrique existe aussi. Employer \item hors de toute liste donne ! LaTeX Error: Lonely \item--perhaps a missing list environment. — typiquement après un \end{itemize} de trop, ou après avoir copié un bloc contenant \item en laissant son \begin derrière. Dans les deux cas le message nomme la cause sans détour : il suffit de suivre le numéro de ligne et de vérifier que les \begin et \end alentour se répondent encore.
Quand une liste à puces se justifie, et quand elle ne se justifie pas
itemize n’est pas de la prose privée de ses connecteurs : c’est un dispositif pour rendre les entrées comparables côte à côte. L’absence de numéros est en soi une déclaration au lecteur : ces quatre éléments n’ont ni ordre ni hiérarchie. Aligner des entrées très inégales en portée, en registre et en longueur, c’est envoyer le lecteur chercher un axe de comparaison qui n’existe pas. Inversement, dès que l’ordre ou la priorité prend du sens, la liste doit devenir un enumerate ; une série de puces qui encode discrètement une séquence est la plus pénible à lire. Voici une liste de contrôle pour la relecture de son propre brouillon.
- Garder une grammaire parallèle. Si la première entrée est un groupe nominal, que toutes le soient ; si l’une est à l’impératif, que toutes le soient.
- Revenir aux paragraphes quand les entrées s’allongent. Si chacune dépasse trois phrases, il s’agit de texte courant avec des intertitres, pas d’une liste.
- Imbriquer deux niveaux au maximum. LaTeX en autorise quatre, mais le lecteur n’en suit généralement que deux.
- Passer à
enumeratedès que l’ordre compte. Avoir envie d’écrire « d’abord » puis « ensuite » est le signal d’une liste numérotée. - Ne changer un marqueur que s’il signifie quelque chose.
\item[$\star$]sert à isoler une entrée, pas à la décorer.