As explained in the enumitem
documentation, the horizontal spacing in lists is composed of the parameters leftmargin
, itemindent
, labelsep
, labelwidth
and labelindent
as follows:
That is to say:
The values obey the relation
leftmargin = labelindent + labelwidth + labelsep - itemindent
The right edge of the \item
label will be indented by labelindent + labelwidth
.
The first line of the Text of the \item
will be indented by leftmargin + itemindent
.
Subsequent lines will be indented by leftmargin
.
As you can see, there are five parameters but they are not all independent. Given any four of them you can calculate the fifth, which is where the !
and *
values to these options come in.
Why have this redundancy at all? Well, in standard LaTeX, the parameter labelindent
does not exist; it is introduced by enumitem
. The author of the package felt that it might be useful to be able to directly set the indentation of the list label instead of having to calculate the other values manually in order to achieve the desired indentation.
By default, the new parameter labelindent
is always calculated from the others. If you want to directly set labelindent
, you will have to tell enumitem
which parameter it should calculate instead. That is what the !
value is for.
*
does exactly the same thing, but it also first sets labelwidth
. This is useful because the right edge of the label is indented by labelindent + labelwidth
, so the left edge of the label will only be indented by exactly labelindent
if the width of the label actually is labelwidth
. enumitem
tries to guess the width of the widest possible label by measuring the width of the label with value
- 0 if
label
is set using \arabic*
,
- viii if
label
is set using \roman*
,
- m if
label
is set using \alph*
and
- similarly for the uppercase versions.
So, if you set label=(\alph*)
, enumitem
will measure the width of (m) and set labelwidth
to this value. You can change this behavior using the widest
option.
Note that this means that labelwidth=!
and labelwidth=*
do exactly the same thing.
Okay, so let's have a look at an example. enumitem
acknowledges that the behavior of these values may be confusing and provides \DrawEnumitemLabel
to visualize the current values, which I will use below. It
[...] draws 4 rules from top to bottom, labelindent
, labelwidth
, labelsep
, itemindent
(thin if positive, thick if negative); the leftmargin
is marked with two vertical rules.
\documentclass{article}
\usepackage{enumitem}
\parindent=0pt
\newcommand*\printvalue[1]{\texttt{\string #1} : \the #1}
\begin{document}
% set some defaults:
\setlist{
label=(\alph*),
leftmargin=50pt,
itemindent=10pt,
labelsep=5pt,
labelwidth=25pt,
labelindent=10pt,
}
By default, my definition of \verb|labelindent| is just ignored and it is calculated from the other values:
\begin{enumerate}
\DrawEnumitemLabel
\item \printvalue\leftmargin
\item \printvalue\itemindent
\item \printvalue\labelsep
\item \printvalue\labelwidth
\item \printvalue\labelindent
\end{enumerate}
I can change that using the \verb|!| value.
For example, I can instead calculate \verb|labelsep| from the other values:
\begin{enumerate}[labelindent=10pt, labelsep=!]
\DrawEnumitemLabel
\item \printvalue\leftmargin
\item \printvalue\itemindent
\item \printvalue\labelsep
\item \printvalue\labelwidth
\item \printvalue\labelindent
\end{enumerate}
The \verb|*| value does exactly the same, only it also set the value of \verb|labelwidth| first.
It tries to guess the widest possible label (\textsl{0} for \verb|\arabic*|, \textsl{viii} for \verb|\roman*|, \textsl{m} for \verb|\alph*|):
\begin{enumerate}[labelindent=10pt, labelsep=*]
\DrawEnumitemLabel
\item \printvalue\leftmargin
\item \printvalue\itemindent
\item \printvalue\labelsep
\item \printvalue\labelwidth
\item \printvalue\labelindent
\end{enumerate}
\end{document}