L'environnement description de LaTeX est le troisième des trois types de listes, aux côtés de itemize et enumerate, mais sa conception n'a rien à voir avec la leur. Ouvrez la définition dans les classes standard : description y fixe \labelwidth à 0pt et \itemindent à moins \leftmargin. Autrement dit, la colonne qui accueille le terme n'a aucune largeur — et c'est voulu. Cette seule ligne explique à la fois la force de description (un terme de n'importe quelle longueur se compose) et son désagrément le plus connu (un terme long pousse l'explication de côté). Cette page examine à quoi sert vraiment l'environnement, d'où vient le gras, et comment le style= de enumitem maîtrise cette poussée.
À quoi sert réellement description
description existe pour composer des couples formés d'un mot et de l'explication de ce mot. Là où itemize et enumerate fournissent eux-mêmes le marqueur — une puce, un numéro — description attend que vous donniez l'étiquette en toutes lettres : ce que vous écrivez dans l'argument optionnel [...] de \item devient le terme. Dans itemize et enumerate, ce [...] est une fonction annexe permettant de remplacer le marqueur d'une entrée ; dans description, c'est toute la raison d'être. Glossaires, listes d'options, documentation de paramètres, liste de personnages — dès que la structure est « un nom, auquel pend une explication », c'est le bon environnement.
\begin{description}
\item[TeX] The typesetting system Knuth wrote.
\item[LaTeX] A document language built on top of TeX.
\item[CTAN] The worldwide archive network that distributes packages.
\end{description}Cette structure correspond exactement à la liste de définitions <dl> / <dt> / <dd> de HTML. Choisir description a donc un sens qui dépasse l'apparence : vous déclarez dans le manuscrit qu'il s'agit d'une définition, et les outils de conversion comme les générateurs d'index savent lire cette intention. Composez la même chose à la main sous la forme \textbf{terme}\quad explication et le rendu se ressemblera, mais l'information structurelle aura disparu. Comme pour itemize et enumerate, il faut au moins un élément ; fermer l'environnement à vide déclenche ! LaTeX Error: Something's wrong--perhaps a missing \item.
D'où vient le gras (\descriptionlabel)
Si un terme est en gras, ce n'est pas à cause de \item[...] mais d'une commande propre à description : \descriptionlabel. Sa définition dans les classes standard tient en une ligne, \hspace\labelsep \normalfont\bfseries #1, et le \bfseries s'y trouve. La distinction se vérifie : écrivez \item[Word] dans un itemize et le PDF produit n'incorpore que le romain du texte — aucune graisse n'apparaît. \item[...] ne fait que remplacer le marqueur ; il n'a aucun pouvoir de mettre quoi que ce soit en gras. Le gras d'une description ne naît que parce que l'environnement confie \descriptionlabel à \makelabel.
Si donc vous ne voulez changer que la fonte, sans enumitem, la voie directe consiste à redéfinir \descriptionlabel par \renewcommand ; son argument #1 est le terme. Voici une version qui compose chaque terme en petites capitales, en conservant le \hspace{\labelsep} initial pour que l'espacement corresponde à la définition d'origine. Remplacez \textsc par \texttt (chasse fixe) ou \textit (italique) pour un autre aspect. Notez encore que si itemize change de marqueur et enumerate de forme de numéro selon la profondeur, description conserve le même style de terme à tous les niveaux d'imbrication. Il n'existe qu'un seul \descriptionlabel : cette redéfinition s'applique donc uniformément à tous les niveaux du document.
% the standard-class definition is:
% \newcommand*\descriptionlabel[1]{\hspace\labelsep \normalfont\bfseries #1}
\renewcommand{\descriptionlabel}[1]{%
{\hspace{\labelsep}\textsc{#1}}}Pourquoi un terme long pousse le texte : labelwidth vaut zéro
Un terme long ne se coupe pas : il pousse vers la droite la première ligne de l'explication, de sa propre largeur. La cause tient en une seule alternative dans latex.ltx : si la boîte d'étiquette est plus large que \labelwidth — \ifdim \wd\@tempboxa >\labelwidth — LaTeX renonce à la boîte de largeur fixe et compose l'étiquette à sa largeur naturelle. Or description fixe \labelwidth à 0pt : même le mot le plus court emprunte toujours cette branche. Un terme de description n'est donc jamais dans une colonne de largeur fixe. Mesuré dans article : \labelwidth 0pt, \itemindent −25,00003pt (soit −\leftmargin), \labelsep 5pt.
Composé puis mesuré, il subsiste toujours après le terme un blanc de 5pt — exactement \labelsep — et il tombe au même endroit que l'on écrive \item[Term]body collé ou \item[Term] body avec une espace. Ce blanc est produit par \labelsep, non par l'espace du source : coller ne sauve donc rien. À partir de la deuxième ligne, le texte redescend à \leftmargin (25pt), si bien que le terme et la deuxième ligne de l'explication n'ont pas le même bord gauche et que l'entrée paraît en escalier. Poussez plus loin — un terme plus large que le bloc de texte — et il déborde dans la marge de droite avec un avertissement Overfull \hbox. La règle pratique : dès qu'un terme dépasse trois ou quatre mots, changez la mise en page elle-même avec la clé style= décrite ci-après.
Changer la mise en page avec font= et style= de enumitem
Une fois enumitem chargé, on peut passer des options directement à description : font= fixe la fonte du terme et style= décide de la disposition même du terme et du corps. Écrivez font=\sffamily\bfseries pour un sans-serif gras, ou font=\ttfamily pour une chasse fixe — plus court que de réécrire \descriptionlabel, et modifiable liste par liste, ce qui en fait le véritable avantage. Les clés communes aux autres types de listes, comme leftmargin=, labelsep= et itemsep=, fonctionnent ici sans changement. C'est style= qui résout le problème de poussée de la section précédente.
| Valeur de style | Comportement quand le terme est long |
|---|---|
standard | Comme dans les classes standard : l'étiquette est encadrée, et ce qui déborde pousse le corps à droite |
unboxed | Proche de standard, mais l'étiquette n'est pas encadrée : un terme long n'est pas à l'étroit et peut se couper |
nextline | Si l'étiquette n'entre pas dans la marge, le corps commence à la ligne suivante ; il n'empiète jamais sur la marge gauche |
sameline | Comme nextline, mais si l'étiquette n'entre pas, le corps se poursuit tout de même sur la même ligne |
multiline | Replie le terme dans la largeur labelwidth, avec césure si nécessaire, et garde le corps aligné à sa droite |
Composez le même terme long sous les cinq valeurs de style= et les différences apparaissent nettement. Avec nextline, le corps tombe à la ligne suivante après un terme long ; avec sameline, il continue sur la même. Pour un terme court, les deux gardent le corps sur la même ligne : la différence n'apparaît donc que lorsque le terme ne rentre pas. multiline est le plus spectaculaire : il replie un terme long dans la labelwidth, avec césure au besoin, et l'empile verticalement — utile dans un glossaire technique aux termes longs, quand on veut que le corps garde un bord gauche rectiligne. Il faut alors indiquer explicitement labelwidth=, faute de quoi aucune largeur de repli n'est définie ; précisez-la avec leftmargin=.
\usepackage{enumitem}
% one list only
\begin{description}[font=\bfseries\sffamily, style=nextline, leftmargin=1.5cm]
\item[A term long enough to overrun its line]
the explanation begins on the next line instead of being shoved sideways
\item[Short] the explanation stays on this line
\end{description}
% or once in the preamble, for every description in the document
\setlist[description]{font=\sffamily\bfseries, style=nextline}Le piège des crochets, et l'omission de l'étiquette
Comme [ et ] délimitent l'argument optionnel, on les cache entre accolades lorsqu'on veut un crochet en tant que caractère. Pour faire de la classe de caractères [a-z] d'une expression régulière un terme, écrivez \item[\texttt{[a-z]}] ; un crochet fermant demande plus de soin encore et s'écrit {]}, comme dans \item[Crochet fermant {]}]. Le cas inverse est tout aussi dangereux : si l'explication commence elle-même par [, enveloppez-la en \item {[}, sinon LaTeX y lira le début d'une étiquette. Dans un document expliquant la syntaxe d'un langage de programmation, les deux se présentent sans cesse.
\begin{description}
\item[\texttt{[a-z]}] a character class; brackets in a label need braces
\item {[}this is how a body starting with a bracket is written
\end{description}Omettez l'étiquette et l'élément n'en a tout simplement aucune : vous obtenez une entrée en forme de paragraphe suspendu, sans marqueur ni indice d'indentation. Puisque l'étiquette est toute la raison d'être de description, évitez-le sauf intention délibérée. Aucune valeur par défaut raisonnable n'existe sur laquelle LaTeX pourrait se rabattre : fournir l'étiquette reste donc toujours votre affaire. Autre point : une commande de changement de fonte écrite sous forme de déclaration dans une étiquette écrase le gras par défaut ; envelopper le tout entre accolades, comme dans \item[{\ttfamily label}], est donc l'habitude sûre.
description ou tableau à deux colonnes : lequel choisir
La ligne de partage pratique : si les explications dépassent une ligne, prenez description ; si les valeurs sont courtes, uniformes et destinées à un balayage vertical, prenez un tableau. Deux colonnes de tabular semblent idéales pour un terme et son explication, mais elles ont trois faiblesses. D'abord, elles ne peuvent pas se couper d'une page à l'autre — il faut convoquer quelque chose comme longtable. Ensuite, c'est à vous de décider des largeurs de colonnes, et un p{5cm} fixe s'effondre dès que la largeur du texte change. Enfin, plus les explications s'allongent, plus seule la colonne de droite s'étire vers le bas, jusqu'à ce que la frontière entre les lignes disparaisse. description ne connaît rien de tout cela : il s'écoule naturellement en paragraphes, se coupe seul entre les pages et suit \textwidth.
À l'inverse, dès qu'une valeur porte plusieurs attributs — type, valeur par défaut, plage —, ce n'est plus une liste de définitions mais un tableau. description convient à une correspondance strictement biunivoque entre un nom et une explication, rien de plus. Au moment où vous souhaitez une troisième colonne, passer à tabular est la bonne décision ; l'y entasser sous la forme \item[nom (type, défaut)] ne fait qu'allonger le terme et vous ramène droit au problème de poussée vu plus haut.