38

I would like to have my lists to have no indent for the top level, i.e. having the same left margin as the surrounding paragraph, with just enough space for the widest label to fit:

Paragraph text
 1. Item
 2. Item
 3. Item
 ...
10. Item
Paragraph text

I already do something similar for itemize and description, using the enumitem package:

\usepackage{enumitem}
\setlist[itemize]{leftmargin=*}
\setlist[description]{leftmargin=*}

But apparently enumerate has some issues determining the width of its labels. It starts with a shaky assumption, which pushes small labels too far to the right, and extends beyond the left margin if the enumeration gets big enough (I know the 10000 value is ridiculous, it's just to make my point obvious):

\documentclass[twocolumn]{scrbook}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\newcommand{\justsometext}{Just enough text to make the line break so we get to see a second line.}

\begin{document}

\justsometext

\begin{enumerate}
\item \justsometext
\begin{enumerate}
\item Nested. \justsometext
\end{enumerate}
\item \justsometext
\addtocounter{enumi}{9997}
\item \justsometext
\end{enumerate}

\justsometext

\end{document}

The enumitem package gives me half of a way around it, but it requires me to state the widest label

\usepackage{enumitem}
\setlist[enumerate]{leftmargin=*}

% ...

\begin{enumerate}[widest=10000]
% ...

However, isn't there some way to make enumerate detect the width of its widest label automatically, instead of having to set it for each individual list? I feel like there must be some way, I just couldn't figure out how from the enumitem doc...

(I tried the paralist package with option alwaysadjust, as well as compactenum from the same package; both are worse than what I got from enumitem: assuming some label width first - pushing the "1." and "2." from the left margin - then ruining the alignment completely when the 10000 label pushes its item to the right...)

1
  • Next best thing I got so far is \setlist[enumerate]{leftmargin=*,widest=0}, and overriding the widest setting for all lists with >9 elements...
    – DevSolar
    Commented Sep 24, 2011 at 8:58

3 Answers 3

33

Here is a way to do it using references, and consequently at least two compilations. It requires using labelwidth rather than widest. First, some background...

The obvious motivation behind itemize and description providing solutions to this without problem is because the former (itemize) uses a single-element (symbol) to denote list items, all of which have the same width (by default). Overriding this default to anything other than a single-element (symbol) will have misaligned items, or item labels protruding margin lines:

\begin{itemize}
  \item An item
  \item[qwerty] An item
  \item An item
\end{itemize}

This is due to the left-aligned nature of the itemized bullets. Another motivation is because lists are typeset "on the fly" and even allow for page breaks between items. So, in order to know the widest item at the start, the entire enumerate environment body would have to be read in memory/parsed before determining the widest, and then typeset - not the case by default. The latter (description) works because it uses a right-aligned approach to typesetting the itemized bullets and has a paragraph-style typesetting of the label and item contents by default.

The solution using enumerate requires setting the following enumitem options for a list:

  • labelindent=0pt: to have a flush left margin;
  • labelwidth=\widthof{\ref{last-item}}: this requires the calc package that measures the width of \ref{last-item} where last-item is a label set for the last item in your list;
  • label=\arabic*.: labels will be arabic, followed by a period .;
  • itemindent=1em: separation/space between label and item; and
  • leftmargin=!: automatically calculate what the leftmargin should be based on the provided parameters above (this is new to version 3.0 of enumitem).

Here is a minimal example highlighting the result:

\documentclass{article}
\usepackage{enumitem}% http://ctan.org/pkg/enumitem
\usepackage{calc}% http://ctan.org/pkg/calc
\begin{document}
\noindent Just enough text to make the line break so we get to see a second line.
\begin{enumerate}[labelindent=0pt,labelwidth=\widthof{\ref{last-item}},label=\arabic*.,itemindent=1em,leftmargin=!]
  \item An item
  \item An item
  \item An item \addtocounter{enumi}{9997}
  \item An item \label{last-item}
\end{enumerate}
Just enough text to make the line break so we get to see a second line.
\end{document}

Dynamically-aligned enumerate label

4
  • There is one problem with this. I was wondering whether you could fix that in your solution. This is the problem: Try making the text in each item be long enough to be not just one line. You'll see that subsequent lines are aligned in a very weird way in each item.
    – meh
    Commented May 27, 2012 at 21:02
  • 1
    Never mind, doing itemindent=0em seems to have fixed it. Thanks for a brilliant answer!
    – meh
    Commented May 27, 2012 at 21:23
  • 5
    Another one of those things which should be handled by default, not by trickery...
    – DevSolar
    Commented Dec 19, 2012 at 10:45
  • This still requires the item with the longest label to be labeled. It would be nice if it was entirely automatic.
    – varkor
    Commented Apr 23, 2021 at 13:27
8

Here is a quick trick, but I'm not sure it works with \include:

\def\maxenumi{0}
\def\saveenumi{0}

\makeatletter
\AtEndDocument{%
  \immediate\write\@auxout{%
    \string\gdef\string\maxenumi{\saveenumi}}}
\makeatother

\usepackage{enumitem}

\setlist[enumerate,1]{%
  leftmargin=*,
  widest=\maxenumi,
  after=\ifnum\value{enumi}>\saveenumi\xdef\saveenumi{\the\value{enumi}}\fi}

Update. See Werner's answer below, which is better, but requires an explicit \label in the last item (which, on the hand, can be moved to after).

0

This can be done using the enumerate package:

\documentclass{article}
\usepackage{enumerate}

\begin{document}
\noindent The quick brown fox jumps over the lazy dog.
\begin{enumerate}[ 1.]
\item First item.
\item Second item.
\setcounter{enumi}{9}
\item Tenth item.
\end{enumerate} 
\end{document}

but I'm not sure how robust this solution is.

2
  • This requires the same predefined knowledge of the maximum-width item; " 1." in your case (note the space in front of 1. to accommodate for arabic numerals up to 99..
    – Werner
    Commented Sep 24, 2011 at 15:45
  • Well, I did say it's not necessarily robust... actually, it's even worse than that; using [ 1.] (two spaces instead of one) doesn't make it work for numbers exceeding 100.
    – einpoklum
    Commented Sep 25, 2011 at 11:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .