18

I am trying to understand the difference between \hfil and \hfill. I always thought that these commands were roughly equivalent except that \hfill was "stronger" than \hfil. As a result, I thought that I could centre a line of text using either of the lines:

\hfil Horizontally centred \hfil

\hfill Horizontally centred \hfill

It turns out that only the first of these snippets actually horizontally centers the text but I do not understand why.

There is a similar issue with \vfil and \vfill. My understanding is that \vfill can be defined as \vspace{\fill}, so it makes sense that you cannot vertically center some text using

\vfill Vertically centered \vfill

because \vspace is ignored at the top of the page. By the same reasoning,

\vspace*{\fill} Vertically centred\vfill

should work and it does, although not quite perfectly. In a similar way, you can use \hspace*{\fill} to horizontally centre text.

Is anyone able to clear explanation of what the differences are between \hfil and \hfill, and between \vfil and \vfill? I am aware of the post What is the difference between 'fil' and 'fill'? but this does not help me.

In trying to understand what is going on I created the following MWE:

\documentclass{article}
\usepackage[paperheight=40mm, paperwidth=80mm,showframe]{geometry}
\parindent=0pt
\begin{document}

  \hfil Horizontally centred \hfil

  \hfill Horizontally centred \hfill

  \hspace*{\fill} Horizontally centred \hfill

  \hfill Horizontally centred \hspace*{\fill}

  \hfil Horizontally centred \hspace*{\fill}

  \newpage

  \vfil Vertically centred\vfil

  \newpage

  \vfill Vertically centred\vfill

  \newpage

  \vspace*{\fill} Vertically centred\vfill

\end{document}

which produces the four pages:

enter image description here

Of course, I know that I can centre text with either

\centerline{Horizontally centred}

\begin{center}Horizontally centred\end{center}

but that's not what I am asking....although I am not convinced that I know the best way to vertically centre text!

  • 2
    In my mental picture \hfil and friends always need something to push against. So I tend to add struts. AFAIR \hspace* automatically adds "stomething to push against – daleif Feb 18 at 8:58
  • @daleifb Thanks! That's a very clean explanation. – Andrew Feb 18 at 9:24
19

The first case: \hfil Horizontally centred \hfil\par (the blank line adds \par).

When \par is processed, the first thing TeX does is \unskip, then it adds a very high penalty, so the next added glue \hskip\parfillskip is not removed. Since the default value of \parfillskip is 0pt plus 1fil, you get centering. Almost, because you have a space after “centred” that's not removed.

The second case: \hfill text\hfill\par (the blank line adds \par).

This works as before, but now the \parfillskip glue is killed by \hfill.

The third case is essentially the same as the second one.

The fourth case: \hfill Horizontally centred \hspace*{\fill} almost centers the text (the space after “centred”, remember), because \unskip doesn't remove \hspace*{\fill} (it internally ends with another glob of glue just for this), because \parfillskip glue is killed.

The fifth case: the \hfil glue at either sides (explicit and provided by \parfillskip respectively) are killed by \hspace*{\fill}.

How do you achieve centering? With

\par{\centering Horizontally centred\par}

For vertical centering,

  1. you have to kill the \topskip glue and the baseline skip glue at the top and the bottom
  2. use \vspace*{\fill} at the top and \vfill (or a more symmetrical \vspace*{\fill}) at the bottom.
\documentclass{article}
\usepackage[paperheight=40mm, paperwidth=80mm,showframe]{geometry}

\setlength{\parindent}{0pt}

\begin{document}

\vspace*{-\topskip}
\vspace*{\fill}
\nointerlineskip
Vertically centred\par
\nointerlineskip
\vfill

\end{document}

enter image description here

|improve this answer|||||
  • Thanks. So, it's all about the glue being killed. So what is the recommended way to vertically centre? – Andrew Feb 18 at 9:23
  • In the first case is there really a space that is not removed? To me it looks like the difference is actually caused by paragraph indentation since \noindent\hfil text\hfil centers the text. – Andrew Feb 18 at 9:49
  • 1
    @Andrew The space preceding \hfil is not removed: \unskip does a single glue removal. Since you set \parindent to 0pt, using \noindent is redundant. – egreg Feb 18 at 9:52
  • Thanks, I was looking at a different example where I had the default \parindent.... – Andrew Feb 18 at 10:09
  • 3
    @Andrew Using \showoutput can help a lot to discover the implicitly-added skips, or to see that whatever skip you thought you added was discarded (at the beginning of a line or page) or removed by \unskip. – frougon Feb 18 at 10:52

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.