9

I am using the tikzposter class to create a poster and have three columns extending almost to the bottom of the page. I would like to stretch the space in between blocks so that the bottoms of the final block in each column line up. A solution which could be modified pad the contents of the block to achieve the same thing would be ideal for if I ever make another poster where the columns are not as similarly sized. I know this is possible in the beamerposter class, but I have no desire to switch poster classes at this late stage (and tikzposter has very nice default themes).

Since tikzposter positions the blocks using tikz, and not the normal LaTeX positioning, it seems like using rubber lengths or \vfill directly is out. So, is there a reasonable way of doing this? I don't mind a solution that hacks around with the tikzposter class itself, or has to write things to the aux file.

  • Welcome to TeX.SX. Please look a our TeX.SX starter guide and help us to help you with a minimal working example (MWE) to work with. – Ignasi May 7 '14 at 6:57
  • You could try putting the block into a \savebox{name}{\begin{minipage}{\linewidth}etc.}, use \settoheight{\length}{\usebox{name}} to determine the size of the block, then compute how much \vspace to add before the \usebox{name} to make it flush to the bottom. (Or use \raisebox.) – John Kormylo May 7 '14 at 14:19
14

I ended up solving it myself. Below is the code I used; if you put it in myposter.sty then use \usepackage[colalign]{myposter} to enable the alignment.

It works by saving the natural heights of all columns into the aux file, along with how many blocks there are. Then next compilation, for each column, it looks at the difference between the stored height and the maximum stored height, divides that by the number of blocks, and adds that much padding inside each block (at the top and bottom.)

\usepackage{letltxmacro}
\usepackage{ifthen}

\newif\ifmy@colalign
\my@colalignfalse

\DeclareOption{colalign}{
    \my@colaligntrue
}

\ProcessOptions\relax

\ifmy@colalign
    % Align the bottoms of columns

    % Declarations
    \newcounter{my@column}
    \newcounter{my@column@loop}
    \newcounter{my@block}
    \newdimen\my@columnextraspace
    \newdimen\my@maxcolheight
    \newdimen\my@colheight
    \newdimen\my@blocktopstart
    \newdimen\my@rounded

    % Store the natural height and number of blocks of the current column in the aux file
    \gdef\my@storecolheight{
        \ifnum\value{my@column} > 0 %
            \expandafter\newdimen\csname my@colheight\alph{my@column}\endcsname
            \expandafter\setlength\csname my@colheight\alph{my@column}\endcsname{\my@colheight}
            \immediate\write\@auxout{\noexpand\newlabel{my@colheight\alph{my@column}}{{\the\my@colheight}{}}}
            \immediate\write\@auxout{\noexpand\newlabel{my@numblocks\alph{my@column}}{{\the\c@my@block}}}
        \fi
    }

    \LetLtxMacro{\orig@block}{\block}

    % Replace the \block command with a version that pads each block by \my@columnextraspace
    \renewcommand{\block}[3][]{%
        \ifTP@columnEnvironment
            \my@blocktopstart=0pt\relax
            \advance\my@blocktopstart-\TP@blocktop
        \fi
        \orig@block[{#1}]{#2}{\vspace*{-0.5\my@columnextraspace}#3\vspace*{-0.5\my@columnextraspace}}
        \ifTP@columnEnvironment
            % count number of blocks
            \stepcounter{my@block}
            % keep track of the height of the current column
            \advance\my@blocktopstart\TP@blocktop
            \advance\my@colheight\my@blocktopstart
            % don't add the padding to the height
            \advance\my@colheight-\my@columnextraspace
        \fi
    }

    % Store the maximum natural height of any column in the aux file
    \gdef\my@storemaxcolheight{
        \ifnum\value{my@column} > 0 %
            \newdimen\my@maxcolheight
            \newdimen\my@colheight@loop
            \setcounter{my@column@loop}{0}
            \loop\ifnum\value{my@column@loop}<\value{my@column}
                \stepcounter{my@column@loop}
                \my@colheight@loop\csname my@colheight\alph{my@column@loop}\endcsname
                \ifnum\my@colheight@loop<\my@maxcolheight
                    \my@maxcolheight\my@colheight@loop
                \fi
            \repeat
            \immediate\write\@auxout{\noexpand\newlabel{my@maxcolheight}{{\the\my@maxcolheight}{}}}
        \fi
    }

    % Read the column height information and calculate how much extra space the current column needs per block
    \gdef\my@calcextraspace{
        \@ifundefined{r@my@maxcolheight}{%
            \my@columnextraspace=0pt\relax
        }{%
            \expandafter\my@maxcolheight\ref{my@maxcolheight}
            \expandafter\my@colheight\ref{my@colheight\alph{my@column}}
            \setcounter{my@block}{\ref{my@numblocks\alph{my@column}}}
            \my@columnextraspace\my@maxcolheight
            \advance\my@columnextraspace-\my@colheight
            \divide\my@columnextraspace by \value{my@block}
        }
    }

    % Replace \column command by a version which stores the height (of the previous column) and calls \my@calcextraspace
    \gdef\column#1{  % #1: relative width
        \ifTP@columnEnvironment
            \my@storecolheight
            \stepcounter{my@column}
            \my@calcextraspace
            \setcounter{my@block}{0}
            \my@blocktopstart0pt
            \my@colheight0pt
            % Now the normal \column command
            \normalsize
            \setlength{\TP@blocktop}{\TP@coltop}
            \setlength{\TP@colcenter}{\TP@colcenter+0.5\colwidth+\TP@colspace}
            \setlength{\colwidth}{#1\TP@visibletextwidth+#1\TP@colspace-\TP@colspace-\blocklinewidth}
            \setlength{\TP@colcenter}{\TP@colcenter+0.5\colwidth+\blocklinewidth}
        \fi
    }

    % Replace the columns environment with a version which stores the height of the final column and the max column
    \renewenvironment{columns}{
        \TP@columnEnvironmenttrue
        \setlength{\TP@colcenter}{-0.5\TP@visibletextwidth-\TP@colspace-0.5\blocklinewidth}
        \global\TP@colcenter=\TP@colcenter
        \global\TP@coltop=\TP@blocktop
        \global\TP@colbottom=\TP@blocktop
        \colwidth=0pt
    }{
        \my@storecolheight
        \my@storemaxcolheight
        \TP@columnEnvironmentfalse
        \global\TP@blocktop=\TP@colbottom
    }
\fi
  • This is awesome! Except for two bugs: 1) doesn't seem to work correctly when there are subcolumns 2) doesn't seem to respect margins: the blocks are stretched all the way to the bottom of the poster. – 12.yakir Jun 26 '14 at 6:34
  • 1
    This is the best. Have you considered releasing it on CTAN? – Lyndon White Dec 3 '15 at 3:26

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.