Automatically set description list `labelwidth` based on widest label?
A variation on egreg's answer to Working with margins
\documentclass{article}
\usepackage{enumitem}
\usepackage{environ}
\newlength\widest
\makeatletter
\NewEnviron{ldescription}{%
\vbox{%
\global\setlength\widest{0pt}%
\def\item[##1]{%
\settowidth\@tempdima{\textbf{##1}}%
\ifdim\@tempdima>\widest\global\setlength\widest{\@tempdima}\fi%
}%
\setbox0=\hbox{\BODY}%
}
\begin{description}[
leftmargin=\dimexpr\widest+0.5em\relax,
labelindent=0pt,
labelwidth=\widest]
\BODY
\end{description}%
}
\makeatother
\begin{document}
\begin{ldescription}
\item[Short] text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text
\item[A really really long label] text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text
\end{ldescription}
\begin{ldescription}
\item[Short] text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text
\item[A medium label] text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text
\end{ldescription}
\end{document}
In the first part, the width of the longest label is calculated: initially, \widest
is set to 0pt
; for each \item
, the length of its optional argument is measured and the length stored in \@tempdima
; if \@tempdima
is greater than \widest
, (this is always true for the first \item
) then \widest
is updated to be \@tempdima
. This is done for all \item
s; \BODY
is set inside a box that is never used. Then, a description
environment is used, setting \labelwidth
to the previously calculated value for \widest
.
Answers to follow-up questions:
- Q: What is the point of
\setbox0=\hbox{\BODY}
?
A: This just boxes\BODY
without typesetting it. - Q: Since
\BODY
is used twice, what happens if\BODY
contains something that has side effects (writes to the.aux
file, contains\newcommand
, contains\footnote
, etc.)?
A: There's no problem with what\BODY
contains (as long as it's reasonable for a standard description, so, for example, sectional unit commands won't be allowed, but they don't make sense in a description anyways). - Q: Why is that stuff wrapped in a
\vbox{}
?
A: The\vbox
is used to prevent the dreadful "Something's wrong--perhaps a missing \item." error at the beginning of a list (\hbox
or\mbox
could have also been used instead).