Las listas de LaTeX quedan demasiado aireadas: por eso suele recurrirse al paquete enumitem, pero pocos han mirado las cifras. En la clase article la distancia entre líneas de base de dos elementos es de 20pt, frente a 12pt de una línea corriente: ocho puntos de aire de más entre cada par de elementos. Esos ocho puntos son dos longitudes, \itemsep (4pt) y \parsep (4pt), y el paquete enumitem existe para reescribirlas directamente mediante opciones clave=valor como itemsep=0pt. Esta página recorre cuánto valen realmente los valores por defecto, qué cambian de verdad nosep y leftmargin=*, y cómo \setlist fija una política para todo un documento, siempre con cifras medidas.
Cuánto valen realmente los ajustes de lista de LaTeX
Medido en article a 10pt, nivel 1: \itemsep vale 4pt, \parsep 4pt, \topsep 8pt, \leftmargin 25pt, \labelwidth 20pt y \labelsep 5pt. Con esas cifras a mano, la queja del «demasiado aire» se vuelve concreta. El hueco vertical que se inserta entre dos elementos es \itemsep más \parsep, 8pt en total; súmese el interlineado de 12pt y salen 20pt. Dentro de un texto compuesto sobre una retícula de 12pt, solo la lista avanza a 1,67 líneas por elemento. Tipográficamente es deliberado: las entradas deben separarse a la vista. Pero diez entradas cortas seguidas dejan la página agujereada. En horizontal, la misma historia: frente a un \leftmargin de 25pt, la viñeta mide menos de 5pt de ancho; 20pt de esa sangría son sencillamente aire.
| Longitud (= nombre de clave) | Valor por defecto de article (nivel 1) | Dónde actúa |
|---|---|---|
itemsep | 4pt (plus 2pt minus 1pt) | Entre un elemento y el siguiente |
parsep | 4pt (plus 2pt minus 1pt) | Entre párrafos dentro de un mismo elemento |
topsep | 8pt (plus 2pt minus 4pt) | Encima y debajo de toda la lista |
partopsep | 2pt (plus 1pt minus 1pt) | Adicional, solo si la lista abre un párrafo nuevo |
leftmargin | 25pt | Sangría de todo el bloque de entradas desde la izquierda |
labelwidth | 20pt | Ancho de la caja de la etiqueta; una etiqueta más ancha sobresale a la izquierda |
labelsep | 5pt | Entre la caja de la etiqueta y el texto de la entrada |
rightmargin | 0pt | El margen derecho; sirve para estrechar la lista por ambos lados, como en una cita |
itemindent | 0pt | Sangría adicional solo en la primera línea de una entrada; un valor negativo la saca a la izquierda |
labelindent | — (clave añadida por enumitem) | Del margen exterior al borde izquierdo de la caja de la etiqueta |
Los valores encogen con la profundidad. En el nivel 2 de itemize, \itemsep y \parsep bajan a 2pt, \topsep a 4pt y \leftmargin a 22pt; en los niveles 3 y 4, \parsep llega a 0pt y \topsep a 2pt, mientras \leftmargin adelgaza a 18,7pt y luego a 17pt. LaTeX parte, pues, de una política que abre sobre todo los niveles superficiales; los anidamientos profundos ya vienen apretados. Por eso el nivel que uno quiere comprimir es casi siempre el nivel 1.
La interfaz clave=valor: las claves son las propias longitudes de LaTeX
Cargado en el preámbulo con \usepackage{enumitem}, los tres entornos itemize, enumerate y description ganan un argumento opcional: pares clave=valor separados por comas dentro de los corchetes configuran esa lista concreta. La clave del diseño es que los nombres de clave son exactamente los nombres de longitud de la tabla anterior. itemsep=1ex reescribe \itemsep; leftmargin=1cm reescribe \leftmargin. Aprender enumitem equivale, pues, a aprender las tripas de las listas de LaTeX, y ahí está su verdadera ventaja frente a la vieja costumbre de sobrescribir comandos internos con \renewcommand. TeX Live 2024 incluye la v3.9 (2019/06/20) de Javier Bezos; kpsewhich enumitem.sty indica qué copia usa su instalación.
\usepackage{enumitem}
% ...
\begin{itemize}[itemsep=1ex, leftmargin=1cm]
\item the key names are the LaTeX length names
\item second entry
\end{itemize}Una misma clave puede sobrescribirse en tres niveles: todo el documento, un tipo de entorno o una lista suelta (mediante \setlist, más abajo). Gana el valor más específico, así que lo ordenado es fijar primero una política global y salirse de ella solo donde haga falta. Si un valor va entero entre llaves, se retira un par exterior (el comportamiento por defecto de keyval): duplíquelas si quiere conservar las llaves mismas.
Compactar una lista: nosep frente a noitemsep
nosep pone a cero cuatro longitudes verticales; noitemsep solo dos. En el código del paquete, nosep fija \partopsep, \topsep, \itemsep y \parsep en 0pt, mientras que noitemsep toca únicamente \itemsep y \parsep. La que se olvida es partopsep: los 2pt que se añaden solo cuando la lista empieza tras una línea en blanco, como párrafo nuevo. Medido, un itemize con nosep deja sus líneas de base de elemento exactamente a 12pt, el mismo espaciado que las líneas de texto corrientes. El espacio por encima y por debajo también desaparece, de modo que la lista se funde por completo con la prosa.
% 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}La elección depende de si la lista debe leerse como parte de la prosa. Cuando las entradas son lo principal —un procedimiento, una diapositiva—, nosep va bien. Para una lista breve incrustada en el cuerpo de un artículo, noitemsep es más seguro: los 8pt de encima y de debajo sobreviven, con lo que la frontera entre párrafo y lista sigue siendo visible. Si se cierra también arriba y abajo, la lista se pega a los párrafos vecinos y cuesta ver dónde empieza y acaba la enumeración. Existe además una clave más antigua, nolistsep, que solo se diferencia de nosep en fijar topsep en 0pt plus .1pt en lugar de un cero limpio; para documentos nuevos, use nosep.
label= y ref=: dar estilo a la etiqueta y a la referencia por separado
La etiqueta de una lista se fija con label=. Dentro del valor, las formas con asterisco \arabic*, \alph*, \Alph*, \roman* y \Roman* representan el contador actual de ese nivel. label=(\arabic*) da (1) (2) (3), label=\alph*) da a) b) c), y label=\Roman*. da I. II. III. Las formas con asterisco no toman argumento; considérelas grafías especiales que solo significan algo dentro de una etiqueta. También existe label*=, que se encadena a la etiqueta del nivel superior: al anidar se acumulan 1., 1.1., 1.2., etc.
\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)"Por defecto, label= gobierna también el aspecto de la referencia cruzada. Ponga un \label en un elemento de una lista declarada solo como [label=(\arabic*)] y \ref imprimirá el (1) entre paréntesis, de donde nace la molestia cotidiana de «vuelva al paso (1)» con paréntesis duplicados. Añada ref=\arabic* y la etiqueta impresa seguirá siendo (1) mientras \ref devuelve un 1 desnudo. Compilar el código anterior lo confirma exactamente. Conviene saber que los valores de label y ref se tratan como argumentos móviles, de modo que un comando frágil dentro de ellos puede requerir \protect; las formas con asterisco de los contadores no dan problema.
Para escribir las etiquetas con la grafía breve del antiguo paquete enumerate, cárguelo como \usepackage[shortlabels]{enumitem}. Entonces una A, a, I, i o 1 como primer elemento entre corchetes equivale respectivamente a \Alph*, \alph*, \Roman*, \roman* o \arabic*, y \begin{enumerate}[(1)] funciona. Resulta cómodo al migrar un manuscrito antiguo fuera del paquete enumerate; en trabajo nuevo, un label= explícito enuncia mejor la intención cuando uno vuelve sobre el texto.
leftmargin=* y wide: dejar que el margen se calcule solo
Las claves horizontales no son independientes: las une una sola ecuación, \leftmargin + \itemindent = \labelindent + \labelwidth + \labelsep. Entregue * a algunas en lugar de un valor y enumitem resuelve la ecuación para las demás. Medido, el efecto es notable: un itemize por defecto tiene \leftmargin en 25pt; con [leftmargin=*] se reduce a 9,99pt, lo justo para alojar la viñeta. Importa más el caso inverso: con una etiqueta ancha como label=(\roman*), «(viii)» no cabe en la caja de 20pt por defecto y sobresale a la izquierda, mientras que leftmargin=* ensancha la caja a la medida de la etiqueta. Siempre que use una etiqueta ancha, escriba leftmargin=* junto a ella y evitará casi todos los accidentes.
La otra clave cómoda es wide. Anula el margen izquierdo y la caja de la etiqueta, de modo que la etiqueta se lee como parte del texto y la entrada se compone como un párrafo corriente. En el código fija \leftmargin y \labelwidth a cero, mete su argumento (por defecto \parindent) en \labelindent, ajusta \listparindent a él y calcula \itemindent con la ecuación. Medido, \leftmargin sale 0pt, \itemindent 20pt y \listparindent 15pt, es decir \parindent. Pase un valor, como wide=0pt, para cambiar la sangría. Es la clave adecuada cuando la maqueta pide listas que no sobresalgan a la izquierda y un bloque de texto con un solo borde izquierdo. Conviene emparejarla con align=, que decide si la etiqueta queda al ras a la izquierda (left), al ras a la derecha (right, por defecto) o en una parbox alineada a la izquierda (parleft).
Empezar en 5, o continuar la lista anterior (start, resume, series)
start= fija el número del primer elemento y resume continúa la numeración del enumerate inmediatamente anterior. Cortar un procedimiento con un párrafo explicativo y retomarlo en «7.» es una necesidad muy frecuente, y hacerlo a mano con \setcounter se rompe en cuanto se inserta un paso más. Compilado de verdad, [start=5] dio 5 y 6; tras un párrafo intercalado, [resume] continuó en 7. Con resume* se hereda no solo el número, sino también los ajustes de opciones de la lista anterior (esta forma con asterisco solo significa algo dentro de los corchetes del entorno).
\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 solo mira la lista inmediatamente anterior, así que no basta cuando varias listas muy separadas —de una sección a otra, por ejemplo— deben llevar un único recuento corrido. Para eso se usa una serie: marque la primera lista con series=nombre y escriba luego resume=nombre o resume*=nombre en las siguientes; la numeración enlaza sin importar lo que haya en medio. Para un procedimiento largo repartido entre secciones, es el único método que aguanta de verdad.
Ajustes para todo el documento con \setlist, y tu propia lista con \newlist
Escribir las mismas opciones cada vez no es realista. \setlist aplica ajustes en bloque a un tipo y un nivel de lista elegidos: \setlist{...} sin corchetes alcanza todos los niveles de todas las listas, \setlist[itemize]{...} todos los niveles de itemize, y \setlist[enumerate,1]{...} solo el nivel 1 de enumerate. El \setlist* con asterisco se suma a los ajustes previos en lugar de sustituirlos. Si quiere corregir en todo un documento el exceso de aire descrito al principio de esta página, una línea de \setlist{noitemsep} en el preámbulo es el cambio con mejor relación entre efecto y esfuerzo.
\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 paso más allá, puede definir su propio tipo de lista. \newlist{nombre}{tipo}{profundidad máxima} clona una de las tres listas básicas (enumerate, itemize o description) en un entorno nuevo, y un \setlist[nombre]{...} posterior le da su aspecto (al menos hay que fijar la etiqueta). Al compilar el código anterior, \begin{steps} produjo «Step 1.» y «Step 2.». La ganancia está menos en el resultado impreso que en la legibilidad del código fuente: ver \begin{steps} le dice al lector que eso es un procedimiento, sin mirar la página. El significado de la lista lo lleva su nombre, no su formato.
Listas en línea dentro de un párrafo (enumerate*)
Cargue el paquete como \usepackage[inline]{enumitem} y obtendrá los entornos con asterisco enumerate*, itemize* y description*, cuyas entradas discurren horizontalmente por el párrafo en lugar de saltar de línea. Compilado, cabe en un solo renglón: «We need (1) flour (2) sugar (3) salt for this.» Cuando solo se enumeran tres o cuatro expresiones breves, esto suele leerse mejor que gastar cuatro líneas de página en una lista aparte; y en la prosa académica, enumerar condiciones así es más bien el estilo estándar.
\usepackage[inline]{enumitem}
% ...
We need
\begin{enumerate*}[label=(\arabic*)]
\item flour \item sugar \item salt
\end{enumerate*}
for this.Los separadores se ajustan con itemjoin (entre elementos; un espacio por defecto), itemjoin* (para un separador distinto justo antes del último elemento: así se obtiene el inglés «a, b, and c») y afterlabel (justo después de la etiqueta; ~ por defecto). Ojo: los elementos de una lista en línea van encajonados por defecto, de modo que flotantes, listas anidadas y ecuaciones aparte no caben dentro; indique mode=unboxed si los necesita. En la práctica, la raya sensata es esta: las listas en línea sirven solo para expresiones breves.