# New environment to vertically center text

Consider the following code:

\documentclass{article}

\usepackage[
papersize = 50mm,
margin = 2mm
]{geometry}

\begin{document}

\topskip0pt
\vspace*{\fill}
test
\vfill

\end{document}


What is the "best" way to define a new environment in order to vertically center the text inside it, i.e., to get the same output as in the example above?

Update

If I try the following, the text goes into the rigth margin and the text doesn't align horizontically.

\documentclass{article}

\usepackage[
papersize = 50mm,
margin = 2mm
]{geometry}

\newenvironment{vc}{\topskip0pt\vspace*{\fill}\noindent}{\vfill}

\begin{document}

\begin{vc}
horse, horse, horse, horse, horse, horse, horse
\end{vc}

\end{document}


-
Why not just use your own code: \newenvironment{vc}{\topskip0pt\vspace*{\fill}}{\vfill} ? – Steven B. Segletes Mar 17 at 15:24
@StevenB.Segletes Because I'm not sure if it is the best way to do it. :-) – Svend Tveskæg Mar 17 at 15:26
"Better still" is the enemy of "good enough". (spoken like a true engineer) – Steven B. Segletes Mar 17 at 15:27
Vertically center with respect to what? The text block? The page? – Werner Mar 17 at 15:33
The indent of your update is corrected with \ignorespaces, as in \newenvironment{vc}{\topskip0pt\vspace*{\fill}\noindent\ignorespaces}{\vfill}. Still thinking about horizontal margins (\sloppy comes to mind). – Steven B. Segletes Mar 17 at 15:43

I started with Svend's proposed code, environmentalized it, and made a few additions.

If you want the \strut top of the first line to be the same distance as the baseline of the last line, then this seems work.

\documentclass{article}

\usepackage[
papersize = 50mm,
margin = 2mm
]{geometry}
\newenvironment{vc}{\topskip0pt\vspace*{\fill}\noindent\ignorespaces}{\strut\vfill}

\begin{document}

\begin{vc}
\sloppy
\fboxsep=-\fboxrule\smash{\fbox{\strut}}%
horse, horse, horse, horse, horse, horse, horse
horse, horse, horse, horse, horse, horse, horse
horse, horse, horse, horse, horse, horse,
\end{vc}

\end{document}


Note that adding a descender letter to the last line doesn't change the vertical spacing. Neither does making the \strut full height on the 1st line, nor does removing the same \strut.

I should note that David's comment below suggests that \noindent\ignorespaces should not be placed in the environement definition because of other problems it creates. In that case, removing that code, the user would need to add \noindent manually to the actual content. Alternately, one could redefine \parindent, as in

\newenvironment{vc}{\parindent0pt\relax\topskip0pt\vspace*{\fill}}{\strut\vfill}


which would have the net effect of removing all paragraph indentation from the environment, while avoiding the use of ignorespaces in the definition.

-
better not to have \noindent than try to mask the problems it creates with \ignorespaces – David Carlisle Mar 17 at 16:10
@DavidCarlisle Are you saying to let the user add \noindent to the actual content, if desired, rather than hardwire it in to the definition? – Steven B. Segletes Mar 17 at 16:13
@DavidCarlisle... and if so, how about adding \parindent 0pt to the environment definition, in lieu of the \noindent\ignorespaces? – Steven B. Segletes Mar 17 at 16:15
yes that would be better, if that's what the OP wants (although the paragraph settings are really a separate issue from the vertical centering) I'd keep them out and then just start the para with \raggedright or whatever if that's what you want in any particular instance (which wouldn't work if the environment has started the paragraph already with \noindent) – David Carlisle Mar 17 at 16:20
@SvendTveskæg Replace \sloppy with \raggedright, either in the content, or add it in the vc environment itself.. – Steven B. Segletes Mar 17 at 16:32

If you want content to be printed in the middle of the page, you may just as well place the content outside of the regular textual flow. The example below uses eso-pic to position the text contained within the vc environment \AtPageCenter:

\documentclass{article}

\usepackage[
papersize = 50mm,
margin = 2mm,
showframe
]{geometry}
\usepackage{eso-pic,environ}

\NewEnviron{vc}[1][\textwidth]{%
\clearpage
\mbox{}
\AtPageCenter{% lower-left anchor at Page Center
\makebox[0pt]{% horizontally centered anchor
\parbox{#1}{\BODY}% Necessarily vertically centered anchor
}%
}%
}
\clearpage
}

\begin{document}

\begin{vc}
horse, horse, horse, horse, horse, horse, horse
\end{vc}

\end{document}


The default width of the text is \textwidth; changeable by specifying an optional argument to the vc environment.

-

It mostly depends on how you want to measure the space. In this code, the distance is measured from the top border to the top of the first line (including ascenders) and from the bottom baseline (ignoring descenders) to the bottom margin.

\documentclass{article}

\usepackage[
papersize = 50mm,
margin = 2mm
]{geometry}
\usepackage{microtype}

\newenvironment{vc}
{\clearpage
\setlength{\topskip}{0pt}%
\setlength{\parindent}{0pt}%
\vspace*{\fill}
\nointerlineskip}
{\vfill}

\begin{document}

\begin{vc}
\hrule height 0.1pt \kern-0.1pt % just for the example
abc abcg abc abcg abc abcg abc abcg
abc abcg abc abcg abc abcg abc abcg
abc abcg abc abcg
\par\vskip-\prevdepth\hrule height 0pt depth 0.1pt \kern-0.1pt % just for the example
\end{vc}

\end{document}


Variations in the measuring are possible.

-
Why are you loading the microtype package? – Svend Tveskæg Mar 17 at 19:46
@SvendTveskæg For reduced text width it's better – egreg Mar 17 at 20:06