# Divide empty vertical space for relative placement of text

I recently learned that I can center a text vertically in the remaining space on a page by using \vfill before and after the text, like so

\documentclass{article}
\usepackage{lipsum}
\def\ctext#1{\begin{center}\MakeUppercase{#1}\end{center}}
\begin{document}
\lipsum[1]
\vfill
\ctext{center}
\vfill
\end{document}


This divides the empty space by 50% before and 50% after the text. Is there a way to generalize this to be able to place text relatively throughout the page? In other words, a command, let's say \vpfill, that creates a vertical space which is a percentage of the space that would be left at the end of the page.

% First page is exactly as before but using \vpfill intsead of \vfill
\lipsum[1]
\vpfill{0.5}
\ctext{center 1}
% \vpfill{0.5} % Unnecessary (?) since 50% of the space remains anyways

\newpage % Second page
\lipsum[1]
\vpfill{0.4}  % Creates space that is 40% of the remaining empty space
\ctext{center 1}
\vpfill{0.2}  % Creates space that is 20% of the remaining empty space
\ctext{center 2}
% \vpfill{0.4}  % Unnecessary (?) since 40% of the space remains anyways


You can give fractional fills and fils (cf. this question) using the primitive \vskip. On pages terminated by \clearpage (like the last page of a document), a \vfil is inserted at the end of the document. Thus, the division you ask for can easily be attained using the following two \vskips.

\documentclass{article}

\begin{document}

Hello World!

\vskip 0pt plus 1fil\relax % 40 % of the remaining space.
foo
\vskip 0pt plus .5fil\relax % 20 % of the remaining space.

Bye World!

% \clearpage inserts a \vfil automatically, i.e. another 40 % of the remaining space.

\end{document}


The ratios you have to calculate to obtain the percentages are the amount of stretch at the place you are considering divided by the total stretch on the page, i.e. 1fil / 2.5fil = 40 % for the first and the last, .5fil / 2.5fil = 20 % for the second \vskip.

Here is something of that sort. It does not require any packages, but only accepts integers which indicate the percentage of the vertical fill. The usage is

\vpfill{<percentage>}
<stuff>
\vrfill


This is the MWE, the geometry package is only loaded because of its showframe option, the purpose of which is to illustrate that this works.

\documentclass{article}
\usepackage[showframe]{geometry}
\usepackage{lipsum}
\def\ctext#1{\begin{center}\MakeUppercase{#1}\end{center}}
\newcounter{pft}
\newcommand{\vrfill}{\vfill}
\newcommand\vpfill[1]{\setcounter{pft}{0}%
\loop\ifnum\value{pft}<#1\relax
\vfill\stepcounter{pft}%
\repeat
\renewcommand{\vrfill}{\vpfill{\the\numexpr100-#1}}}
\begin{document}
\lipsum[1]
\vfill
\ctext{center}
\vfill
\newpage
\lipsum[1]
\vpfill{25}
\ctext{center}
\vrfill
\newpage
\lipsum[2]
\vpfill{60}
\ctext{center}
\vrfill
\end{document}


One can generalize this to work with permille, or any fractions, if needed.

\documentclass{article}
\usepackage[showframe]{geometry}
\usepackage{lipsum}
\def\ctext#1{\begin{center}\MakeUppercase{#1}\end{center}}
\newcounter{pft}
\newcommand{\vrfill}{\vfill}
\newcommand\vpfill[2][100]{\setcounter{pft}{0}%
\loop\ifnum\value{pft}<#2\relax
\vfill\stepcounter{pft}%
\repeat
\renewcommand{\vrfill}{\vpfill{\the\numexpr#1-#2}}}
\begin{document}
\lipsum[1]
\vfill
\ctext{center}
\vfill
\newpage
\lipsum[1]
\vpfill[1000]{333}
\ctext{333/1000 of the remaining space}
\vrfill
\newpage
\lipsum[2]
\vpfill[1111]{789}
\ctext{333/1111 of the remaining space}
\vrfill
\end{document}


Maybe a simple (cumbersome) solution would be to use \vfill multiple times. With this you can get any percentages, depending on how often you repeat \vfill.

\documentclass{article}
\usepackage{lipsum}
\def\ctext#1{\begin{center}\MakeUppercase{#1}\end{center}}
\begin{document}
\lipsum[1]
\vfill\vfill        %   40%
\ctext{center 1}
\vfill              %   20%
\ctext{center 2}
\vfill\vfill        %   40%
\end{document}

\documentclass{article}
\usepackage{lipsum}
\def\ctext#1{\begin{center}\MakeUppercase{#1}\end{center}}
\begin{document}
\lipsum[1]
\vspace{.5\textheight}
\ctext{center 1}
\newpage
\lipsum[1]
\vspace{.4\textheight}
\ctext{center 1}
\vspace{.2\textheight}
\ctext{center 2}
\end{document}


Note that in top of page \vspace{....} does not work, but \vspace*{...} does.

• I think \textheight is the height of the page rather than the empty space, so this is not exactly what I am looking for. Mar 6, 2020 at 9:22
• @Tohiko, Is the height of the text area, not of the whole page, but yes, is not what you asked, I did not read the question carefully, sorry.
– Fran
Mar 6, 2020 at 18:10