Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

This question was originally a duplicate of How can I add vertical space to a beamercolorbox to make it align with another one?. The response to that question was to add a vertical space according to the largest column, as Seamus explains in the comments. I would like, however, to do this in an automatic way.

I rephrase my question.

First, here is the original question, which I leave with minor modifications so that the motivation remains clear. Then, I will analyze and explain the new, rephrased question.


Original question

When using the columns environment in beamer, I sometimes find myself with these situation: two columns with some contents (like a block) whose height are different. The result is that each element appears with its height:

I think that if both columns had the same height (the max of all columns), the presentation would be more elegant (at least with the presentation that I am currently creating).

Normally I add some \vspace with a length determined by trial-and-error. Needless to say, this is an annoying process. I would like to force the contents of a column to have the same height as the largest column.

The example above was generated by this code:

\documentclass{beamer}

\usetheme{Darmstadt}
\usefonttheme[onlylarge]{structurebold}
\setbeamerfont*{frametitle}{size=\normalsize,series=\bfseries}
\setbeamertemplate{navigation symbols}{}


\begin{document}

\begin{frame}{A frame}
  \begin{columns}[T]
    \begin{column}{0.5\linewidth}
      \begin{block}{A block}
        Hello
      \end{block}
    \end{column}
    \begin{column}{0.5\linewidth}
      \begin{block}{Another block}
        This one has a larger height since it has an itemize
        \begin{itemize}
        \item item a
        \item item b
        \end{itemize}
      \end{block}
    \end{column}
  \end{columns}
\end{frame}

\end{document}

New question

I have examined beamerbaserequires.sty looking for the definition of the columns and column environment. In order to resize each column, I think it is necessary to rewrite part of the code, since a column is implemented as a minipage without a height parameter. My new question is, as the title says, How to modify columns/column environments so they resize automatically to the largest column ?

My first thoughts on how to achieve this are the following:

  1. Resizing each column to the largest one may not be possible with one pass. It is only when the columns environment is closed that we could know the correct size and at that time it is too late to modify each column.
  2. At the code that "closes" a column could add a vertical space equal to the size of the largest column so far.
  3. The size of the largest column could be written and read from the aux file or some other temporal file, so that, in a second pass, all columns are resized correctly.

These guidelines are probably incorrect, implausible or too difficult to implement, since I have nearly no experience coding in TeX/LaTeX. Any comments regarding these ideas are welcome as well.

PS. I hesitate whether this question has become too specific (or even too broad), or if it should become a community wiki...

share|improve this question
    
I'm pretty sure we've had this sort of question before. The basic answer was "no, the easiest way is to add vspace manually." But there are smart ways of working out exactly how much vspace to add. For example if it's just text, then add the right number of \baselineskips. It's more complex if you've got itemize etc, but still possible to calculate it. (Or use phantom) –  Seamus Mar 25 '11 at 12:35
    
Aha: found it IS this a duplicate or do you want to make your question more specific? –  Seamus Mar 25 '11 at 13:16
    
@Seamus: Ok, I think that I will rewrite my question focusing on how to change the columns/column environment so that it does this automatically. PS: sorry I did not respond earlier, I went away for the weekend –  YuppieNetworking Mar 28 '11 at 9:01
2  
This new question seems worthy of a bounty. Any takers? –  Seamus Jun 22 '11 at 8:41
1  
So, basically you seem to want a vertical version of the eqparbox package? –  Lev Bishop Jun 22 '11 at 16:20
show 4 more comments

1 Answer 1

up vote 21 down vote accepted
+100

One way to do this is to collect the whole columns content e.g. using the environ package, which stores the environment body in \BODY. Redefine column to measure the natural height of each column as well as remembering the maximum height in a first pass and then typeset the columns in a second pass where a \vspace is inserted with the correct adjustment.

I use here a counter to store the heights in unique macros which are then used to define the \autoheight macro with the right amount. This \autoheight macro must be placed where the extra height is required, e.g. before \end{box}. It can and should be placed in all columns and will be just \vspace*{0pt} for the largest column. It would also be possible to add this macro to all \end{box}, e.g. using the etoolbox package and \preto{\endbox}{\autoheight}. Also the columns environment could be redefined instead of using acolumns so no frame code must be adjusted at all. However, this makes the application less flexible. For example if there are two boxes in one column both would be resized incorrectly. However, this could also be implemented, e.g. by counting the number of boxes per column and spread the height accordantly. (This is left as exercise to the reader ;-) )

Limitations:

  • Does not support verbatim content like lstlistings even when the fragile option is set for the frame.
  • Does not support cascaded columns (yet). This is because some values are set globally.

Both of these could be avoided with some extra effort.

\documentclass{beamer}

\usetheme{Darmstadt}
\usefonttheme[onlylarge]{structurebold}
\setbeamerfont*{frametitle}{size=\normalsize,series=\bfseries}
\setbeamertemplate{navigation symbols}{}

\usepackage{environ}% Required for \NewEnviron, i.e. to read the whole body of the environment
\makeatletter

\newcounter{acolumn}%  Number of current column
\newlength{\acolumnmaxheight}%   Maximum column height


% `column` replacement to measure height
\newenvironment{@acolumn}[1]{%
    \stepcounter{acolumn}%
    \begin{lrbox}{\@tempboxa}%
    \begin{minipage}{#1}%
}{%
    \end{minipage}
    \end{lrbox}
    \@tempdimc=\dimexpr\ht\@tempboxa+\dp\@tempboxa\relax
    % Save height of this column:
    \expandafter\xdef\csname acolumn@height@\roman{acolumn}\endcsname{\the\@tempdimc}%
    % Save maximum height
    \ifdim\@tempdimc>\acolumnmaxheight
        \global\acolumnmaxheight=\@tempdimc
    \fi
}

% `column` wrapper which sets the height beforehand
\newenvironment{@@acolumn}[1]{%
    \stepcounter{acolumn}%
    % The \autoheight macro contains a \vspace macro with the maximum height minus the natural column height
    \edef\autoheight{\noexpand\vspace*{\dimexpr\acolumnmaxheight-\csname acolumn@height@\roman{acolumn}\endcsname\relax}}%
    % Call original `column`:
    \orig@column{#1}%
}{%
    \endorig@column
}

% Save orignal `column` environment away
\let\orig@column\column
\let\endorig@column\endcolumn

% `columns` variant with automatic height adjustment
\NewEnviron{acolumns}[1][]{%
    % Init vars:
    \setcounter{acolumn}{0}%
    \setlength{\acolumnmaxheight}{0pt}%
    \def\autoheight{\vspace*{0pt}}%
    % Set `column` environment to special measuring environment
    \let\column\@acolumn
    \let\endcolumn\end@acolumn
    \BODY% measure heights
    % Reset counter for second processing round
    \setcounter{acolumn}{0}%
    % Set `column` environment to wrapper
    \let\column\@@acolumn
    \let\endcolumn\end@@acolumn
    % Finally process columns now for real
    \begin{columns}[#1]%
        \BODY
    \end{columns}%
}
\makeatother

\begin{document}
\begin{frame}{A frame}
  \begin{acolumns}[T]
    \begin{column}{0.5\linewidth}
      \begin{block}{A block}
        Hello
        \autoheight
      \end{block}
    \end{column}
    \begin{column}{0.5\linewidth}
      \begin{block}{Another block}
        This one has a larger height since it has an itemize
        \begin{itemize}
        \item item a
        \item item b
        \end{itemize}
        \autoheight
      \end{block}
    \end{column}
  \end{acolumns}
\end{frame}

\end{document}

Result

share|improve this answer
2  
Brilliant. That's a contender for the TeX.sx package, surely? –  Seamus Jun 26 '11 at 12:30
    
@Seamus: Sure. I like to get some suggestions for the to be used user interface. –  Martin Scharrer Jun 26 '11 at 12:48
    
+1 Excellent! Sorry I've been quiet even though I was the OP, I was away for some weeks. –  YuppieNetworking Jun 27 '11 at 13:22
1  
@MartinScharrer there's a little problem with spaces with your solution, see acolumns environment modifies columns widths. David Carlisle solved it, is it ok if I update your answer? –  capitalaslash May 7 '12 at 10:05
    
@capitalaslash: Thanks for notifying me. I made the change now. –  Martin Scharrer May 7 '12 at 10:09
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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