# Problem with vertical alignment of a multicolumn listing in a tcolorbox

TLDR: current remaining questions are at the bottom of the post

Consider the following test code:

% ---------------------------------------------------------------------------- %
% Files
\begin{filecontents*}{empty\jobname.cpp}
\end{filecontents*}
\begin{filecontents*}{\jobname.cpp}
0000
0000
\end{filecontents*}
\begin{filecontents*}{multi\jobname.cpp}
0000
0000
0000
0000
\end{filecontents*}
% ---------------------------------------------------------------------------- %
% Preamble
\documentclass[letterpaper, 12pt, onecolumn]{article}
% ---------------------------------------------------------------------------- %
% Packages
\usepackage[paperwidth = 160mm, paperheight = 550mm, margin = 10mm]{geometry}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{multicol}
\usepackage[most]{tcolorbox}
% ---------------------------------------------------------------------------- %
% Listings options
\newtcbinputlisting{\inputcode}[4][\normalsize]{
code = {},
enhanced,
listing only,
top = 0pt,
bottom = 0pt,
left = 0pt,
right = 0pt,
arc = 0pt,
outer arc = 0pt,
boxsep = 0pt,
titlerule = 0pt,
colback = blue,
colframe = black,
boxrule = 2pt,
title = {\centering{\fontfamily{cmtt}\selectfont#2\strut}},
listing options = {
language = C++,
framesep = 0pt,
rulesep = 0pt,
aboveskip = 0pt,
belowskip = 0pt,
backgroundcolor = \color{lightgray},
basicstyle = \fontfamily{cmtt}\selectfont#1,
#3,
},
listing file={#4},
}
% ---------------------------------------------------------------------------- %
% Commands
\newcommand{\makelisting}[2]{%
\inputcode[#1]{#2}{}{\jobname.cpp}%
\inputcode[#1]{#2}{multicols = 2}{multi\jobname.cpp}%
\bigskip\bigskip%
}
% ---------------------------------------------------------------------------- %
% Document
\pagestyle{empty}
\begin{document}
\inputcode[]{empty}{}{empty\jobname.cpp}
\inputcode[]{empty}{multicols = 2}{empty\jobname.cpp}
\bigskip\bigskip
\makelisting{\tiny}{tiny}
\makelisting{\scriptsize}{scriptsize}
\makelisting{\footnotesize}{footnotesize}
\makelisting{\small}{small}
\makelisting{\normalsize}{normalsize}
\makelisting{\large}{large}
\makelisting{\Large}{Large}
\makelisting{\LARGE}{LARGE}
\makelisting{\huge}{huge}
\makelisting{\Huge}{Huge}
\end{document}
% ---------------------------------------------------------------------------- %


It produces pairs of listings in tcolorboxes: one without multicolumn and the other with multicolumn. The resulting output:

As illustrated on these images, the multicols option ends up adding extra space at the top and at the bottom of the listing (in blue on the image). The exact measurement of this spacing seems to depend on the font style of the listing (\tiny, \small, \large...), as well as the font size of the document (10pt, 11pt, 12pt). Doing the experiment with an empty listing (beginning of the document) also shows that there is a remaining blue spacing when the multicols option is activated.

So far, I have not been able to understand where this vertical spacing was coming from, and where its exact value was coming from.

Questions:

• Where is this extra spacing coming from (at the top, and at the bottom of the listing)?
• How is its value (at the top and at the bottom) computed?
• How to make this extra vertical spacing disappear?

UPDATE 1:

After hours of research, here is a small finding. If the top parameter is adjusted to the following:

\newlength{\normalsizestrutheight}
\settoheight{\normalsizestrutheight}{\strut}
\newlength{\fontstrutheight}
\newcommand{\getfontstrutheight}[1]{\settoheight{\fontstrutheight}{#1\strut}}
\newlength{\topshift}
\newcommand{\computetopshift}[1]{%
\getfontstrutheight{#1}%
\setlength{\topshift}{%
\minof{-\normalsizestrutheight + \fontstrutheight}{0pt}%
}%
}


then for all fonts smaller to \normalsize, the remaining top space is constant. Still not zero, but at least contant. However, the value of this constant still depends on the default font size of the document (10pt, 11pt, 12pt, 8pt (with extarticle), 17pt (with extarticle)...), in a manner for which I'm still unable to find a formula.

Here is my updated test file:

% ---------------------------------------------------------------------------- %
% Files
\begin{filecontents*}{empty\jobname.cpp}
\end{filecontents*}
\begin{filecontents*}{\jobname.cpp}
0000
\end{filecontents*}
\begin{filecontents*}{multi\jobname.cpp}
0000
0000
0000
0000
\end{filecontents*}
% ---------------------------------------------------------------------------- %
% Preamble
\documentclass[letterpaper, 12pt, onecolumn]{article}
% ---------------------------------------------------------------------------- %
% Packages
\usepackage[paperwidth = 160mm, paperheight = 500mm, margin = 10mm]{geometry}
\usepackage{calc}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{multicol}
\usepackage{printlen}
\usepackage[most]{tcolorbox}
% ---------------------------------------------------------------------------- %
% Measurement computation
\newlength{\normalsizestrutheight}
\settoheight{\normalsizestrutheight}{\strut}
\newlength{\fontstrutheight}
\newcommand{\getfontstrutheight}[1]{\settoheight{\fontstrutheight}{#1\strut}}
\newlength{\topshift}
\newcommand{\computetopshift}[1]{%
\getfontstrutheight{#1}%
\setlength{\topshift}{%
\minof{-\normalsizestrutheight + \fontstrutheight}{0pt}%
}%
}
% ---------------------------------------------------------------------------- %
% Listings options
\newtcbinputlisting{\inputcode}[5][\normalsize]{
code = {\computetopshift{\fontfamily{cmtt}\selectfont#1}},
enhanced,
listing only,
top = 0pt,
bottom = 0pt,
left = 0pt,
right = 0pt,
arc = 0pt,
outer arc = 0pt,
boxsep = 0pt,
titlerule = 0pt,
colback = red,
colframe = black,
boxrule = 2pt,
title = {\centering{\fontfamily{cmtt}\selectfont#2\strut}},
listing options = {
language = C++,
framesep = 0pt,
rulesep = 0pt,
aboveskip = 0pt,
belowskip = 0pt,
backgroundcolor = \color{white},
basicstyle = \fontfamily{cmtt}\selectfont#1,
#3,
},
#4,
listing file={#5},
}
% ---------------------------------------------------------------------------- %
% Commands
\newcommand{\makeempty}{%
\inputcode[]{empty}{}{}{empty\jobname.cpp}%
\inputcode[]{empty}{multicols = 2}{}{empty\jobname.cpp}%
\bigskip\bigskip%
}
\newcommand{\makelisting}[3]{%
\inputcode[#1]{#2}{}{}{\jobname.cpp}%
\inputcode[#1]{#2}{multicols = 2}{top = \topshift, #3,}{multi\jobname.cpp}%
\bigskip\bigskip%
}
% ---------------------------------------------------------------------------- %
% Document
\pagestyle{empty}
\begin{document}
\makeempty{}
\makelisting{\tiny}{tiny}{}
\makelisting{\scriptsize}{scriptsize}{}
\makelisting{\footnotesize}{footnotesize}{}
\makelisting{\small}{small}{}
\makelisting{\normalsize}{normalsize}{}
\makelisting{\large}{large}{}
\makelisting{\Large}{Large}{}
\makelisting{\LARGE}{LARGE}{}
\makelisting{\huge}{huge}{}
\makelisting{\Huge}{Huge}{}
\end{document}
% ---------------------------------------------------------------------------- %


and the output:

However, how to make this remaining top space disappear in a generic manner that would work for every default document font size, as well as the bottom space, are still mysteries.

UPDATE 2:

I tried to compute the value of the constant that I just described ie the remaining space between the tcolorbox and the top of the listing for a given document font size \documentclass[Npt]{extarticle} for N=8, 9, 10, 11, 12, 14, 17, 20. I used the following code:

\newlength{\normalsizestrutheight}
\settoheight{\normalsizestrutheight}{\strut}
\newlength{\fontstrutheight}
\newcommand{\getfontstrutheight}[1]{\settoheight{\fontstrutheight}{#1\strut}}
\newlength{\topconstant}
\setlength{\topconstant}{% something here %}
\newlength{\topshift}
\newcommand{\computetopshift}[1]{%
\getfontstrutheight{#1}%
\setlength{\topshift}{%
\minof{-\normalsizestrutheight + \fontstrutheight - \topconstant}{0pt}%
}%
}


If you follow, I was wondering for a given N what were the values of topconstant that would make the top extra spacing disappear. Here are the approximate values I collected:

value of N -> value of topconstant
8pt -> 2.350pt
9pt -> 1.335pt
10pt -> 1.600pt
11pt -> 1.480pt
12pt -> 1.850pt
14pt -> 2.100pt
17pt -> 1.600pt
20pt -> 2.500pt


If anyone has any idea where these values are coming from and how to compute them automatically, that would be wonderfull. The other remaining question is how to deal with the extra bottom spacing.

UPDATE 3:

I think I found something. With the following code:

\newlength{\mainfontsize}
\makeatletter
\setlength{\mainfontsize}{\@ptsize}
\makeatother
\newlength{\normalsizestrutheight}
\settoheight{\normalsizestrutheight}{\strut}
\newlength{\fontstrutheight}
\newcommand{\getfontstrutheight}[1]{\settoheight{\fontstrutheight}{#1\strut}}
\newlength{\topshift}
\newcommand{\computetopshift}[1]{%
\getfontstrutheight{#1}%
\setlength{\topshift}{%
\minof{-\mainfontsize + \fontstrutheight}{0pt}%
}%
}


the extra top spacing disappear... except for \documentclass[8pt]{extarticle}. For that specific case, \mainfontsize needs to be set equal to 9pt. More surprisingly it works for extarticle but not for article.

• Any idea why there is this subtelty for a font size of 8pt in extarticle?
• Why does it work for extarticle and not for article?
• And still, how to get rid of the bottom spacing?

UPDATE 4: REMAINING QUESTION

After Ulrike Fischer's answer, the question of the bottom spacing remains open. Through tests I also found out that the extra bottom spacing depends of whether there is an even or odd number of lines in the listing.

If you set \topskip and \mathdepth locally to 0pt and (e.g. with before upper*) it seems to work with the exception of the empty case.

\begin{filecontents*}{empty\jobname.cpp}
\end{filecontents*}
\begin{filecontents*}{\jobname.cpp}
0000
0000
\end{filecontents*}
\begin{filecontents*}{multi\jobname.cpp}
0000
0000
0000
0000
\end{filecontents*}
% ---------------------------------------------------------------------------- %
% Preamble
\documentclass[letterpaper, 12pt, onecolumn]{article}
% ---------------------------------------------------------------------------- %
% Packages
\usepackage[paperwidth = 160mm, paperheight = 550mm, margin = 10mm]{geometry}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{multicol}
\usepackage[most]{tcolorbox}
% ---------------------------------------------------------------------------- %
% Listings options
\newtcbinputlisting{\inputcode}[4][\normalsize]{
code = {},
before upper*={\topskip0pt \maxdepth=0pt}, %<---------------
enhanced,
listing only,
top = 0pt,
bottom = 0pt,
left = 0pt,
right = 0pt,
arc = 0pt,
outer arc = 0pt,
boxsep = 0pt,
titlerule = 0pt,
colback = blue,
colframe = black,
boxrule = 2pt,
title = {\centering{\fontfamily{cmtt}\selectfont#2\strut}},
listing options = {
language = C++,
framesep = 0pt,
rulesep = 0pt,
aboveskip = 0pt,
belowskip = 0pt,
backgroundcolor = \color{lightgray},
basicstyle = \fontfamily{cmtt}\selectfont#1,
#3,
},
listing file={#4},
}
% ---------------------------------------------------------------------------- %
% Commands
\newcommand{\makelisting}[2]{%
\inputcode[#1]{#2}{}{\jobname.cpp}%
\inputcode[#1]{#2}{multicols = 2}{multi\jobname.cpp}%
\bigskip\bigskip%
}
% ---------------------------------------------------------------------------- %
% Document
\pagestyle{empty}
\begin{document}
\inputcode[]{empty}{}{empty\jobname.cpp}
\inputcode[]{empty}{multicols = 2}{empty\jobname.cpp}
\bigskip\bigskip
\makelisting{\tiny}{tiny}
\makelisting{\scriptsize}{scriptsize}
\makelisting{\footnotesize}{footnotesize}
\makelisting{\small}{small}
\makelisting{\normalsize}{normalsize}
\makelisting{\large}{large}
\makelisting{\Large}{Large}
\makelisting{\LARGE}{LARGE}
\makelisting{\huge}{huge}
\makelisting{\Huge}{Huge}
\end{document}


• Great! However the question still holds for the few pixels at the bottom. – Vincent Apr 27 '19 at 20:36
• I edited the answer. – Ulrike Fischer Apr 28 '19 at 12:48