# Separate page vertically at variable height

Other Explanation:

This is a template at mark #1 there is an table inserted and at mark #3 some text. The text and table which are inserted are of different size for each dataset. Normally both fit on one page but some are longer. So for the normal case that both are less then half a page long the \rule (mark #2) should stay vertically centered. In any other case that one is bigger than half a page it should move up or down and if the table (mark #1) is longer than 1 page it even should move to the next page. In the case that there are two pages it would be nice to have the \rule (mark #2) centered on the second page, if the text (mark #3) is not to long, but that is not necessary.

How to keep the \rule (mark #2) vertically at the center of the page?

If the table (mark #1) grows it should move the \rule (mark #2) down or to the next page. If the text (mark #3) grow it should move the \rule(mark #2) up before starting a new page.

The content table and text is generated by a python script and is not the same size for every data set.

Is there an easy way to do it? Or do I have to get the size of text and table and calculate the value for a variable \vspace.

\documentclass{scrartcl}
\usepackage{longtable}
\usepackage{tabu}
\usepackage{blindtext}

\begin{document}
\begin{longtabu}{XXX} %#1
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
\vfill
\noindent\rule[1mm]{1.0\textwidth}{2pt} %#2
\blindtext %#3
\vfill
\end{document}


I am using \vfill at the moment to keep the content of the page spread out somewhat evenly, but my goal would be to keep the \rule (mark #2) at the center of the page for as many documents and for as long as possible. The the table and text (mark #1 and #2) are filled with python and text and table have no fixed length. So it is possible that the document is longer than one page and also that the \rule (mark #2) is on the second page.

Some exampls:

| Table height (mark #1) | Text height (mark #3) | Rule at about x from top  |
|------------------------|-----------------------|---------------------------|
| 0.25\textheight        | 0.25\textheight       | 0.50\textheight           |
| 0.60\textheight        | 0.25\textheight       | 0.60\textheight           |
| 0.25\textheight        | 0.60\textheight       | 0.40\textheight           |
| 1.50\textheight        | 0.25\textheight       | next Page 0.50\textheight |


Solution:

Below is what I am using now. It is based on answer of cfr and supports multiple pages, so that the \rule stays centered on the following pages or if it is necessary to start a new page because of the bottom text.

It is the first time that I did something like that, so if there is something wrong or a better way please tell me.

\documentclass{scrartcl}
\usepackage{longtable}
\usepackage{tabu}
\usepackage{calc}
\usepackage{blindtext}

\newlength{\mytopheight}
\newlength{\mybotheight}
\newcommand*\mymidrule{\noindent\rule[1mm]{\linewidth}{2pt}}

\newlength{\targetheight}
\setlength{\targetheight}{\dimexpr\textheight-2pt-2\baselineskip-2\parskip}% if an adjustment is needed for the rule width

\newlength{\mybotoversize}
\newlength{\myspacing}

\newlength{\lengtha}

\newsavebox{\mytop}
\newsavebox{\mybot}

\setlength{\parindent}{0pt}

\newcommand\myrulesplit[2]{%
\sbox{\mytop}{%
\begin{minipage}[t]{\linewidth}
#1
\end{minipage}%
}%
\sbox{\mybot}{%
\begin{minipage}[t]{\linewidth}
#2
\end{minipage}%
}%
\settototalheight{\mytopheight}{\usebox{\mytop}}%
\settototalheight{\mybotheight}{\usebox{\mybot}}%
\loop
\ifdim\mytopheight>\textheight
\setlength{\mytopheight}{\dimexpr\mytopheight-\textheight}%
\repeat
\loop
\ifdim\mybotheight>\textheight
\setlength{\mybotheight}{\dimexpr\mybotheight-\textheight}%
\repeat
\setlength{\mybotoversize}{\dimexpr\mybotheight-.5\targetheight}
\ifdim\mybotoversize<0pt\setlength{\mybotoversize}{0pt}\fi % if smaler than half of the available space
\setlength{\myspacing}{\dimexpr.5\targetheight-\mytopheight}
\ifdim\mybotoversize<\myspacing\setlength{\myspacing}{\dimexpr\myspacing-\mybotoversize}\fi % bottom smaler then available space move rule
\ifdim\myspacing<0pt\setlength{\myspacing}{0pt}\fi % if page is full
#1\par\vspace*{\myspacing}\mymidrule\par#2
% mytopheight:\the\textheight\\
% mytopheight:\the\mytopheight\\
% mybotheight:\the\mybotheight\\
% mybotoversize:\the\mybotoversize\\
% myspacing:\the\myspacing\\
}

\begin{document}
\myrulesplit{%
\begin{longtabu}{XXX} %#1
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
}{%
\blindtext

\blindtext

\blindtext

\blindtext
}
\clearpage
\myrulesplit{%
\begin{longtabu}{XXX} %#1
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
}{%
\blindtext

\blindtext
}
\clearpage
\myrulesplit{%
\begin{longtabu}{XXX} %#1
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
}{%
\blindtext

\blindtext

\blindtext

\blindtext
}
\clearpage
\myrulesplit{%
\begin{longtabu}{XXX} %#1
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
}{%
\blindtext
}
\clearpage
\myrulesplit{%
\begin{longtabu}{XXX} %#1
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
}{%
\blindtext
}
\clearpage
\myrulesplit{%
\begin{longtabu}{XXX} %#1
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
}{%
\blindtext

\blindtext

\blindtext
}
\clearpage
\myrulesplit{%
\begin{longtabu}{XXX} %#1
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
}{%
\blindtext
}
\end{document}

• I think you simply want to have both \vfill staying with the rule. Nov 22, 2014 at 15:26
• No that would move the text to the bottom of the page and the \rule would also not be at the center of the page. Nov 22, 2014 at 15:39
• Isn't that the intended behaviour if the rule should be placed vertically centered between tabular material and text? Nov 22, 2014 at 15:41
• probably you could look at flowfram package with the table in a flowframe set up for the top of the page and the text in a frame for the bottom of the page. Nov 22, 2014 at 16:19
• @user66689 Sorry but either you want the rule vertically centred on the page or you want it to move. You can't have both. If it is to be always vertically centred, it cannot also move in response to the size of the text or table (which you say it should in your comment on John Kormylo's answer). So I'm confused. As it stands, I simply don't understand your question.
– cfr
Nov 22, 2014 at 18:20

If I've understood your question, this may, possibly do something vaguely of the kind you want. But I'm very far from confident about this!

\documentclass{scrartcl}
\usepackage{longtable}
\usepackage{tabu}
\usepackage{calc}
\usepackage{blindtext}
\newlength{\mytopheight}
\newlength{\mybotheight}
\newcommand*\mymidrule{\noindent\rule[1mm]{\linewidth}{2pt}}
\newlength{\targetheight}
\setlength{\targetheight}{\dimexpr\textheight-2pt-2\baselineskip-2\parskip}% if an adjustment is needed for the rule width
\newlength{\lengtha}
\newsavebox{\mytop}
\newsavebox{\mybot}
\newlength{\normalparindent}
\setlength{\normalparindent}{\parindent}
\newcommand\myrulesplit[2]{%
\sbox{\mytop}{%
\begin{minipage}[t]{\linewidth}
\setlength{\parindent}{\normalparindent}%
#1
\end{minipage}%
}%
\sbox{\mybot}{%
\begin{minipage}[t]{\linewidth}
\setlength{\parindent}{\normalparindent}%
#2
\end{minipage}%
}%
\settototalheight{\mytopheight}{\usebox{\mytop}}%
\ifdim\mytopheight>.5\targetheight#1\par\mymidrule\par#2
\else
\settototalheight{\mybotheight}{\usebox{\mybot}}%
\ifdim\mybotheight>.5\targetheight
\setlength{\lengtha}{\dimexpr\mytopheight+\mybotheight}%
\ifdim\lengtha>\targetheight#1\par\mymidrule\par#2
\else#1\vfill\par\mymidrule\par#2%
\fi
\else
\smash{\usebox{\mytop}}\vfill\par\mymidrule\par\smash{\usebox{\mybot}}\vfill%
\fi
\fi
}

\begin{document}
\myrulesplit{%
\begin{longtabu}{XXX} %#1
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
}{%
\blindtext

\blindtext
}
\clearpage
\myrulesplit{%
\begin{longtabu}{XXX} %#1
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
}{%
\blindtext

\blindtext

\blindtext

\blindtext
}
\clearpage
\myrulesplit{%
\begin{longtabu}{XXX} %#1
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
}{%
\blindtext
}
\end{document}


• Thank you. I learned a lot from it. I changed it to fit my needs a little better, see above. Nov 23, 2014 at 13:32
• @user66689 You are welcome. You should present your solution as an answer, though, rather than including it in your question.
– cfr
Nov 23, 2014 at 16:44

This is one way. The \raisebox takes up precisely half the page.

\documentclass{scrartcl}
\usepackage{longtable}
\usepackage{tabu}
\usepackage{blindtext}

\newsavebox{\tempbox}

\begin{document}
\noindent\raisebox{-\height}[0pt][0.5\textheight]{%
\begin{minipage}{\textwidth}
\begin{longtabu}{XXX} %#1
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
\end{minipage}}
\noindent\rule[1mm]{1.0\textwidth}{2pt} %#2
\blindtext %#3

\end{document}


Here is another. Since each \vfill expands to the same size, the space taken up above and below must be identical. \smash causes them to effectively take up no space. One can use \rlap and \llap to achieve the same effect horizontally.

\documentclass{scrartcl}
\usepackage{longtable}
\usepackage{tabu}
\usepackage{blindtext}

\newsavebox{\tempbox}

\begin{document}
\noindent\smash{\begin{minipage}[t]{\textwidth}
\begin{longtabu}{XXX} %#1
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{longtabu}
\end{minipage}}
\vfill
\noindent\rule[1mm]{1.0\textwidth}{2pt} %#2
\noindent\smash{\begin{minipage}[t]{\textwidth}
\blindtext %#3
\end{minipage}}
\vfill
\end{document}

• But its a fixed size, so if the text or table grows the \rule dos not move. I edited the main question maybe it makes it clearer. Nov 22, 2014 at 17:45