9

Inserting an \hphantom to indent a table row works in tabular, but in tabulary it produces extra vertical space instead.

Since these are left-aligned L columns I would expect the space at the left edge to be preserved, while the space on the right is variable. Why does this happen and how could I fix it?

\documentclass{article}
\usepackage{tabulary}

\newcommand{\sator}{Sator arepo tenet opera rotas}
\newcommand{\tabindent}{\hphantom{em}}

\begin{document}

\section{Tabular}

\begin{tabular}{ll}
\sator  & \sator\\
\tabindent\sator & \tabindent\sator\\
\end{tabular}

\section{Tabulary}

\begin{tabulary}{\textwidth}{LL}
\sator  & \sator\\
\tabindent\sator & \tabindent\sator\\
\end{tabulary}

\end{document}

enter image description here

  • 1
    This doesn't depend on tabulary; it's the same whenever you have \hphantom in vertical mode (after a blank line or paragraph or at the start of a \parbox). – egreg Dec 9 '14 at 18:18
  • @egreg Oh, I see, it is the same if I use p{} columns in tabular, because each column is a paragraph. – musarithmia Dec 9 '14 at 18:25
12

\hphantom isn't really a documented LaTeX command and it's a good occasion for talking about it.

The problem can be seen also in this simpler document, which shows that tabulary is not involved:

\documentclass{article}

\newcommand{\sator}{Sator arepo tenet opera rotas}
\newcommand{\tabindent}{\hphantom{em}}

\begin{document}

\sator

\tabindent\sator

\end{document}

enter image description here

Why the “blank line”? Because \hphantom doesn't start a paragraph, because it is essentially equivalent to

\hbox{...}

where ... is some space (the implementation is not really this, however).

Solution: use \leavevmode

\documentclass{article}

\newcommand{\sator}{Sator arepo tenet opera rotas}
\newcommand{\tabindent}{\leavevmode\hphantom{em}}

\begin{document}

\sator

\tabindent\sator

\end{document}

enter image description here

The definition of \hphantom is

% latex.ltx, line 4137:
\def\hphantom{\v@false\h@true\ph@nt}

The macro \ph@nt is

% latex.ltx, line 4139:
\def\ph@nt{%
  \ifmmode
    \expandafter\mathpalette\expandafter\mathph@nt
  \else
    \expandafter\makeph@nt
  \fi}

Leaving aside the case of math mode, which is irrelevant here, let's see \makeph@nt:

\def\makeph@nt#1{%
  \setbox\z@\hbox{\color@begingroup#1\color@endgroup}\finph@nt}

The argument to \hphantom is actually the argument to \makeph@nt; a box is set to contain it and \finph@nt is called.

% latex.ltx, line 4149:
\def\finph@nt{%
  \setbox\tw@\null
  \ifv@ \ht\tw@\ht\z@ \dp\tw@\dp\z@\fi
  \ifh@ \wd\tw@\wd\z@\fi \box\tw@}

The dimensions of \box0 set by \makeph@nt are used to change the dimensions of an empty box (depending on the fact whether \hphantom, \vphantom or \phantom is called, some are changed and some aren't). Then TeX issues

\box\tw@

which delivers the (empty) contents of the box occupying the stated horizontal or vertical space. Such a command never changes the mode TeX's in, so horizontal mode (paragraph building) is not started.

In the case of tabular, TeX is in (restricted) horizontal mode, so the problem doesn't appear.


These macros are taken literally from plain.tex; there's a nice discussion of the matter in the TeXbook: the concept of “phantom” led Knuth to adding \iftrue and \iffalse to TeX, so \ifv@ and \ifh@ are always either \iftrue or \iffalse and conditionals can be properly nested.

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.