13

Code:

\documentclass{article}
\usepackage[a5paper]{geometry}
\usepackage{multicol}
\setlength{\parindent}{0cm}
\begin{document}
\begin{multicols}{2}
  \begin{enumerate}
  \item text 1
  \item text 2
  \item text 3
  \item text 4
  \item text 5
  \end{enumerate}
\end{multicols}
\end{document}

Gives this:

enter image description here

How to move "text 5" upwards adjacent to "text 4"?

3
  • Use \begin{multicols*}{2} ... \end{multicols*}. – jon May 28 '13 at 21:10
  • related: enumerate in multicols – cmhughes May 28 '13 at 23:22
  • @jon the star form is not solving the problem here as that prevents balancing (which is wanted) but with 3+2 lines only "partial balancing" not stretched out. – Frank Mittelbach Sep 1 '13 at 21:20
6

Use the \raggedcolumns command. Based on a suggestion from David Carlisle in chat I've added a command the adjust the spacing after the enumerate environment. I'm not sure how this works, or why the problem arises in the first place.

\documentclass{article}
\usepackage[a5paper]{geometry}
\usepackage{multicol}
\setlength{\parindent}{0cm}
\newcommand{\fixspacing}{\vspace{0pt plus 1filll}\mbox{}}
\begin{document}
\raggedcolumns
\begin{multicols}{2}
  \begin{enumerate}
  \item text 1
  \item text 2
  \item text 3
  \item text 4
  \item text 5
  \end{enumerate}
  \fixspacing
\end{multicols}
\end{document}

output of code

4
  • How can I put "text 5" on the same line with "text 2"? Now it's a little bit lower. – user4035 May 28 '13 at 21:37
  • I've updated the answer with a manual fix, due to David Carlisle. – Alan Munn May 29 '13 at 2:00
  • 1
    @AlanMunn -- why does it work? the \mbox{} at the end adds a dummy line, which aligns with item 3 on the left, and the 3-ell filll overpowers the usual 2-ell fill that's inserted with \raggedcolumns, so the spacing between the last "actual" item and the bottom of the column becomes the same as the distance between the next-to-last line and the bottom of the left-hand column. if the items are short, and only one line each, not a problem; if some multi-line items, not so sure the baselines can be guaranteed to match. – barbara beeton May 29 '13 at 12:47
  • @user4035 the differences in positioning are a result of the multicol balancing approach, see my answer – Frank Mittelbach Sep 1 '13 at 19:17
6

The normal behavior of the multicols environment is to balance the columns so that they are all of (roughly) equal vertical length. If a the columns contain vertical stretchable space (as it happens in the example) then multicols will use this stretch or shrink component as part of the balancing process. Especially in the last column this may result in some visible holes, es long as the result is still technically within the bounds of specified "badness".

The suggested fix (by David and Alan) in the other answer adds strongly vertical stretchable space at the end of the last column and therefore the other space(s) do not expand.

There is actually a different (and possibly simpler) way to get to the same result: multicols has the parameter \finalcolumnbadness which decides whether or not the last column is being vertically justified or set at its natural height. The idea is that if the last column would get a "badness" > \finalcolumnbadness then justification is abandomed and the column is set to its natural height (i.e., the suggested fix is actually applied internally). Thus all that would be necessary is to set this parameter to a suitable value, e.g.

 \setcounter{finalcolumnbadness}{1000}

would achieve the same as \fixspacing in the other answer.

However, neither is giving the right result if you look closely, the position of text 5 is slightly lower than text 2 in the first column. (I added some rules to make this better visible):

enter image description here

So why is this the case?

We have to think about how multicols does its balancing:

  • It starts with by calculating a minimal column height based on the material it has to balance (in fact it starts a bit lower).
  • Then it cuts off all columns to this height (except for the last).
  • Then it looks at the height of the remaining material. If it is smaller than the height of the other columns - fine.
  • If not, it looks if it is possible to squeeze that material into the wanted column height. If that does work and the resulting badness is not too "bad" (see \finalcolumnbadness above) then the trial is considered a success. There are a few other tests that are done, but for the purpose of this discussion they are unimportant.
  • If the trail was a failure then multicols starts another trial, this time enlarging the trial height by 1pt. And eventually this will result in a successful trial.

So what is the problem with this approach?

The issue is that the moment the first column contains some strechable or shrinkable space (and it does in our example) it is more than likely that a solution will be found where the first column is not set at its natural height, but slightly compressed or stretched. However, with aboce fix will set the last column at its natural height and ergo, the baselines will not end up in the same positions.

Now can anything be done about this?

Not generally if you think about it unless you devices a very complicated algorithm that looks at all columns and their badness and makes those values part of the success/failure. But even then you can easily dream up examples that then result in problems or have no solution whatsoever.

But there is something that can be done which will help in many cases and this is implemented in the patch below.

The answer is simple:

  • Start the trial with a column height that is a multiple of \baselineskip (or rather that plus \topskip for the first line); this is already the case so nothing to be changed here.

  • But then increment not by a point but increment by \baselineskip

This gives a higher chance (not a guarantee) that columns are typeset at their natural height. The code for this looks like this:

\makeatletter
\newcommand\balanceincrement{\baselineskip}

\edef\reset@newlinechar{\newlinechar\the\newlinechar}\newlinechar-1 % hack needed for patching \balance@columns

\patchcmd{\balance@columns}{\advance\@tempdima\dp\mult@box}{}{\typeout{Success}}{\typeout{Fail!!}}
\patchcmd{\balance@columns}{\advance\dimen@-\p@}{\advance\dimen@-\balanceincrement\relax}{\typeout{Success}}{\typeout{Fail!!}}
\patchcmd{\balance@columns}{\advance\dimen@\p@}{\advance\dimen@\balanceincrement\relax}{\typeout{Success}}{\typeout{Fail!!}}

\reset@newlinechar
\makeatother

If we apply this to the example we get:

enter image description here

and that's much more like it should be. This would also help enormously for people who try to use grid based typesetting as now the results from a multicols gets predictable in height.

And if we want a different increment (or the old behavior back) then

\renewcommand\balanceincrement{1pt}

will do the trick.

2

Just add one extra \item with no text. That worked for me.

1
  • 2
    This by itself will balance things but introduces an item label (6.) it might be preferable to use \item[] instead which will produce an item where the label is replaced by blank space. – Dai Bowen Sep 16 '16 at 0:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.