# Inconsistent spacing after multicols inside figure

I have a document with three columns of text in which I am positioning figures at the bottom of certain pages. These figures contain lists of items across three columns. Here is what this looks like:

In the first figure to be output, there is less space between the bottom of the columns and the bottom of the figure. Compare the figure on page 2 with the figure on page 3:

As should be apparent, there is less space between 'India', 'Romeo', and 'Alfa' and the bottom of the figure on page 2 than there is on page 3 (and page 4, not pictured).

The problem appears to lie with the multicol package. The problem with spacing disappears if e.g. just the first column of items is typeset without multicol. But I would like to use multicol if possible. Setting \multicolsep to 0pt (or some other length) has no effect.

How can I have these figures all appear consistently using multicol, such that the baseline of the final row of items is always the same distance from the bottom of the figure?

I would prefer a shorter distance like that pictured on page 2.

(Removing the \strut in \newcommand\blockitem[1]{\par#1\strut} makes a small cosmetic difference, but the problem still remains and it is nevertheless needed for the baselines of each row of items to be aligned.)

MWE:

\documentclass{article}

\usepackage{geometry}
\usepackage{multicol}
\usepackage{lipsum}

\geometry{b4paper}

\newcommand\blockitem[1]{\par#1\strut}

\newsavebox{\demobox}
\newenvironment{blocklist}
{\begin{figure*}[!b]
\begin{lrbox}{\demobox}\begin{minipage}[b][][b]{\textwidth}
\begin{multicols}{3}
}
{\end{multicols}
\end{minipage}\end{lrbox}\fbox{\usebox{\demobox}}
\end{figure*}
}

\begin{document}

\begin{multicols}{3}
\lipsum[1-8]
\begin{blocklist}
\blockitem{Alfa} \blockitem{Bravo} \blockitem{Charlie} \blockitem{Delta} \blockitem{Echo} \blockitem{Foxtrot} \blockitem{Golf} \blockitem{Hotel} \blockitem{India} \blockitem{Juliett} \blockitem{Kilo} \blockitem{Lima} \blockitem{Mike} \blockitem{November} \blockitem{Oscar} \blockitem{Papa} \blockitem{Quebec} \blockitem{Romeo} \blockitem{Sierra} \blockitem{Tango} \blockitem{Uniform} \blockitem{Victor} \blockitem{Whiskey} \blockitem{X-ray} \blockitem{Yankee} \blockitem{Zulu} \blockitem{Alfa}
\end{blocklist}
\lipsum[1-8]
\begin{blocklist}
\blockitem{Alfa} \blockitem{Bravo} \blockitem{Charlie} \blockitem{Delta} \blockitem{Echo} \blockitem{Foxtrot} \blockitem{Golf} \blockitem{Hotel} \blockitem{India} \blockitem{Juliett} \blockitem{Kilo} \blockitem{Lima} \blockitem{Mike} \blockitem{November} \blockitem{Oscar} \blockitem{Papa} \blockitem{Quebec} \blockitem{Romeo} \blockitem{Sierra} \blockitem{Tango} \blockitem{Uniform} \blockitem{Victor} \blockitem{Whiskey} \blockitem{X-ray} \blockitem{Yankee} \blockitem{Zulu} \blockitem{Alfa}
\end{blocklist}
\lipsum[1-8]
\begin{blocklist}
\blockitem{Alfa} \blockitem{Bravo} \blockitem{Charlie} \blockitem{Delta} \blockitem{Echo} \blockitem{Foxtrot} \blockitem{Golf} \blockitem{Hotel} \blockitem{India} \blockitem{Juliett} \blockitem{Kilo} \blockitem{Lima} \blockitem{Mike} \blockitem{November} \blockitem{Oscar} \blockitem{Papa} \blockitem{Quebec} \blockitem{Romeo} \blockitem{Sierra} \blockitem{Tango} \blockitem{Uniform} \blockitem{Victor} \blockitem{Whiskey} \blockitem{X-ray} \blockitem{Yankee} \blockitem{Zulu} \blockitem{Alfa}
\end{blocklist}
\lipsum[1-8]
\end{multicols}

\end{document}


## 1 Answer

You're seeing this behavior because of the way that you're composing the savebox on the fly and inserting it as a bottom figure. You insert two or more multicols environments into bottom figures before the output routine has had a chance to work, and this triggers what I believe should count as a bug in multicol (although admittedly this is an edge case).

What happens is this:

The first time a multicols environment is composed, the columns are split correctly. It is then inserted as a figure*, and as part of that process, @addtobot is called. One side effect of that routine is that \maxdepth is globally set to zero.

If a page is then output, this will be reset and there's no problem. But if you insert another multicols environment into the figure list before that happens, then multicol uses that 0 value for \maxdepth. That means that it splits the columns incorrectly and takes too little text, leaving an overly long final line. It then is forced to try to iterate through several attempts to balance the columns, and when it succeeds, the end result is that the column height is larger than it should be by the actual depth of the bottom line (in your case, .3\baselineheight because of the strut).

One way to work around this would simply be to pre-compose your saveboxes. Another possibility, used in the the solution below, is to patch multicol so that the balancing routine uses the correct value for \maxdepth.

\documentclass{article}

\usepackage{geometry}
\usepackage{multicol}
\usepackage{lipsum}
\usepackage{xpatch}

\geometry{b4paper}

\makeatletter
\xpatchcmd{\balance@columns}{\splitmaxdepth\maxdepth}{\splitmaxdepth\@maxdepth}
{\typeout{balance@columns patch 1 succeeded}}
{\typeout{balance@columns patch 1 failed}}
\xpatchcmd{\balance@columns}{\boxmaxdepth\maxdepth}{\boxmaxdepth\@maxdepth}
{\typeout{balance@columns patch 2 succeeded}}
{\typeout{balance@columns patch 2 failed}}
\makeatother

\newcommand\blockitem[1]{\par#1\strut}

\newsavebox{\demobox}

\newenvironment{blocklist}{%
\begin{lrbox}{\demobox}
\begin{minipage}[b]{\textwidth}
\begin{multicols}{3}}{%
\end{multicols}
\end{minipage}
\end{lrbox}%
\begin{figure*}[!b]
\fbox{\usebox{\demobox}}
\end{figure*}
}

\begin{document}

\begin{multicols}{3}
\lipsum[1-8]
\begin{blocklist}
\blockitem{Alfa} \blockitem{Bravo} \blockitem{Charlie} \blockitem{Delta} \blockitem{Echo} \blockitem{Foxtrot} \blockitem{Golf} \blockitem{Hotel} \blockitem{India} \blockitem{Juliet} \blockitem{Kilo} \blockitem{Lima} \blockitem{Mike} \blockitem{November} \blockitem{Oscar} \blockitem{Papa} \blockitem{Quebec} \blockitem{Romeo} \blockitem{Sierra} \blockitem{Tango} \blockitem{Uniform} \blockitem{Victor} \blockitem{Whiskey} \blockitem{X-ray} \blockitem{Yankee} \blockitem{Zulu} \blockitem{Alfa}
\end{blocklist}
\lipsum[1-8]
\begin{blocklist}
\blockitem{Alfa} \blockitem{Bravo} \blockitem{Charlie} \blockitem{Delta} \blockitem{Echo} \blockitem{Foxtrot} \blockitem{Golf} \blockitem{Hotel} \blockitem{India} \blockitem{Juliet} \blockitem{Kilo} \blockitem{Lima} \blockitem{Mike} \blockitem{November} \blockitem{Oscar} \blockitem{Papa} \blockitem{Quebec} \blockitem{Romeo} \blockitem{Sierra} \blockitem{Tango} \blockitem{Uniform} \blockitem{Victor} \blockitem{Whiskey} \blockitem{X-ray} \blockitem{Yankee} \blockitem{Zulu} \blockitem{Alfa}
\end{blocklist}
\lipsum[1-8]
\begin{blocklist}
\blockitem{Alfa} \blockitem{Bravo} \blockitem{Charlie} \blockitem{Delta} \blockitem{Echo} \blockitem{Foxtrot} \blockitem{Golf} \blockitem{Hotel} \blockitem{India} \blockitem{Juliet} \blockitem{Kilo} \blockitem{Lima} \blockitem{Mike} \blockitem{November} \blockitem{Oscar} \blockitem{Papa} \blockitem{Quebec} \blockitem{Romeo} \blockitem{Sierra} \blockitem{Tango} \blockitem{Uniform} \blockitem{Victor} \blockitem{Whiskey} \blockitem{X-ray} \blockitem{Yankee} \blockitem{Zulu} \blockitem{Alfa}
\end{blocklist}
\lipsum[1-8]
\end{multicols}
\end{document}

• thanks for that, but it is not quite enough patching. If you alter the test then it still fails. Fix is in github.com/latex3/latex2e/commit/… and will be released in the next LaTeX release in spring. – Frank Mittelbach Oct 15 '19 at 20:40
• Yeah, I realized that there were other instances of \maxdepth that should have been patched, but I was lazy and went for the minimal fix for this particular case, under the assumption that you would likely prepare a more comprehensive solution anyway. – Karl Hagen Oct 16 '19 at 5:49
• sure :-) but ... – Frank Mittelbach Oct 16 '19 at 7:22