[Tex/LaTex] In beamer class, how to remove the additional vertical space before an itemize environment

beameritemizelistsminipagevertical alignment

On a beamer slide, I want to produce something like

I use the following LaTeX code, which works well in LaTeX with the article class.

\begin{minipage}[t]{1.4cm}
Questions:
\end{minipage}\nobreak
\begin{minipage}[t]{9cm}
\begin{itemize}
\item 1st question;
\item 2nd question.
\end{itemize}
\end{minipage}

With the beamer class, however, I don't get the horizontal alignment correct: There is some additional vertical space above the itemize environment, and I don't manage to remove it. (Is it some \topsep or \partopsep? I tried the package enumitem, but this only made things worse.)

What is a good way to solve this problem? Are there fixes for the itemize, or should I use a totally different approach?

EDIT1:

OK, with Juan's help I have father pinpointed the problem. Let me first elaborate on what the remaining alignment problem is: Yes, Juan, you're right, at the first sight it seems to be pixel perfect. But if you really magnify (3000% or so), then you see that it isn't. It gets worse and much easier visible if you change "1st question" to "1st question $(*)$". You get perfect alignment if you change "1st question" to "Questions:" (really helpful …). So the contents of the first \item really matters.

I've checked with article class; there the alignment is 100% perfect. A very funny thing: In this case you mustn't use the \vspace{0pt} hack since it destroys the desired alignment.

EDIT2:

Juan's answer provides a great fix for my problem, but to me it doesn't seem like the final solution. Is this strange behaviour of the beamer class a bug or a feature?

Best Answer

It took me two years :-) but now I know what's happening and how to fix it. The main point is that \begin{minipage}[t] creates a \vtop box, which is responsible for alignment at the top. Now one needs to read the TeXbook, bottom of pageĀ 81:

The final height x [of the \vtop box] is defined to be zero unless the very first item inside the new vbox is a box; in the latter case, x is the height of that box.

This means: If the minipage starts with some text (possibly broken into lines, which TeX has put into \hboxes), then the vertical alignment of the \vtop box doesn't take place at the very top of the box but at the baseline of the first line of text in the box. And this is exactly what one wants here, alignment of the baselines (red):

alignment of the baselines of the first lines

However, if the minipage does not start with a box, but e.g. with a color change, then one doesn't obtain alignment of the baselines; instead, the baseline of the word "Questions" is aligned with the top of the second minipage, like this:

baseline of "Questions" aligned with top of 2nd minipage

How to fix the problem

According to the above explanation of the behavior of \vtop, the solution will be to make sure that the very first item inside the \vtop box is the \hbox containing the first line of text. Thus, we have to avoid any \kerns, color changes etc. at the top of the minipage. In the code below I roughly explain the main ideas. The code is tested with various combinations of overlay commands and manual color changes.

\documentclass{beamer}
\makeatletter
\def\beamer@callorigitem{%
  \@ifnextchar[
    \beamer@@callorigitem
    {\beamer@origitem
     \if@minipage\else
       \kern0pt  % don't put the \kern at the top of a \minipage
     \fi
     \ignorespaces
    }%
  }
\newcommand*\if@minipage@and@vmode[2]{%
  \let\mini@vmode 0%
  \if@minipage\ifvmode
    \let\mini@vmode 1%
  \fi\fi
  \if\mini@vmode 1 #1\else #2\fi
}
% Redefine \beamerorig@set@color, \pgfsys@begininvisible and \pgfsys@endinvisible
% such that they don't act at the top of a \minipage;
% instead save the corresponding commands in \set@minipage@color ...
\def\set@minipage@color{}%
\let\save@beamerorig@set@color\beamerorig@set@color
\def\beamerorig@set@color{%
  \if@minipage@and@vmode{%
    \begingroup
    \def\reset@color{\relax}%
    \xdef\addto@minipage@color{\save@beamerorig@set@color}%
    \endgroup
    \expandafter\g@addto@macro\expandafter\set@minipage@color
                              \expandafter{\addto@minipage@color}%
    \aftergroup\reset@color
  }{%
    \save@beamerorig@set@color
  }%
}
\let\save@pgfsys@begininvisible\pgfsys@begininvisible
\let\save@pgfsys@endinvisible\pgfsys@endinvisible
\def\pgfsys@begininvisible{%
  \if@minipage@and@vmode
    {\g@addto@macro\set@minipage@color{\save@pgfsys@begininvisible}}
    {\save@pgfsys@begininvisible}%
}
\def\pgfsys@endinvisible{%
  \if@minipage@and@vmode
    {\g@addto@macro\set@minipage@color{\save@pgfsys@endinvisible}}
    {\save@pgfsys@endinvisible}%
}
% ... and execute them at the beginning of the first paragraph of the minipage
% (where \everypar issues \@minipagefalse).
\let\save@minipagefalse\@minipagefalse
\def\@minipagefalse{%
  \set@minipage@color
  \gdef\set@minipage@color{}%
  \save@minipagefalse
}
\makeatother
\begin{document}
\begin{frame}
\begin{minipage}[t]{1.6cm}
Questions:
\end{minipage}\nobreak
\begin{minipage}[t]{9cm}
\begin{itemize}
\item 1st question;
\item 2nd question.
\end{itemize}
\end{minipage}
\end{frame}
\end{document}

If one compiles this with

\tracingoutput=2
\showboxbreadth=\maxdimen \showboxdepth=\maxdimen

in the preamble, then in the log file one finds the lines

.....\vbox(7.43904+18.72917)x256.0748
......\hbox(7.43904+2.12917)x234.17474, glue set 87.88736fil, shifted 21.90005

This tells that the second minipage is a \vbox with a height of 7.43904pt and a depth of 18.72917, and that the first item inside the \vbox is an \hbox. Without my redefinitions of \beamer@callorigitem, \beamerorig@set@color, \pgfsys@begininvisible and \pgfsys@endinvisible, one will find

.....\vbox(0.0+26.16821)x256.0748
......\pdfcolorstack 0 push {0 g 0 G}
......\kern 0.0

in the log file instead. This means that the second minipage is a \vbox with height 0pt (and one sees the color change and the \kern responsible for this!).

How to "officially" fix it

The problem isn't really beamer specific, except for the \kern0pt in \beamer@callorigitem from beamerbaseoverlay.sty. One gets the same misalignment with the article document class if one uses, e.g., \color{red} at the top of the minipage. The changes to \beamerorig@set@color (which is \let to \set@color by beamer) and to \@minipagefalse would best fit into the xcolor package; the changes to \pgfsys@begininvisible and \pgfsys@endinvisible should go to pgfsys.code.tex.