# Why does center not center \halign?

With the following code:

\documentclass[a4paper]{report}
\begin{document}
\begin{center}
\halign{\vrule \hfil # \hfil & \hfil # \hfil \vrule \cr
a & b \cr\noalign{\hrule}
c & d \cr\noalign{\hrule}
}
\end{center}
\end{document}


I'd expect to get the simple table produced with \halign centered in the page. However, it is not, as the picture below shows.

\centering also has no effect. Why does that happen?

• This is consistent with most other primitives that make boxes center would have no effect on \hbox{a} either. Compare with LaTeX commands such as \mbox{a} (or tabular) which are centred. – David Carlisle Sep 28 '14 at 9:12

One might be tempted of using low level commands also in LaTeX; however there are some subtleties in them that are not easy to grasp at the beginning.

One of these subtleties is that \halign is a vertical command, so when found it causes vertical mode to start; if TeX is in horizontal mode when it scans \halign, it quits it by issuing \par.

This is proved by the following test file (Plain TeX):

a\def\par{PAR\endgraf\let\par\endgraf}bc\halign{#\cr HALIGN\cr}def
\bye


that outputs

The temporary redefinition of \par is aimed at showing that \par is effectively executed.

When TeX is in vertical mode, it simply stacks boxes without making paragraphs; therefore \centering (which is in effect in center) does nothing, because it only influences paragraphs. Thus your \halign will be printed flush with the left margin, since \tabskip is normally zero. The \tabskip glue in force at the moment \halign is scanned is added the left of every box formed by \halign (one box for every alignment row) and between any two alignment cells unless another \tabskip is specified. Read chapter 22 in the TeXbook for more information, but it's not easy.

How can one make \halign part of a paragraph? By hiding it inside something that can and that can also contain it: a \vbox is usually employed (the most common device for centering tables in Plain TeX is to use \vbox{\halign{...}}; don't try it in LaTeX). While \vbox doesn't by itself start a paragraph, it doesn't interrupt it either, so

\begin{center}
\leavevmode\vbox{\halign{...}}
\end{center}


Use tabular; you'll be on the safe side.

• you mention \halign{...} in Plain, but doesn't one still need a \vcenter or \vbox around \halign? – user4686 Sep 28 '14 at 11:24
• @jfbu Of course! – egreg Sep 28 '14 at 12:22
• And I certainly will @egreg. The reason I used it is I had a huge array which I wanted to convert to tabular for text mode, and since it was a table of LaTeX commands the column defaults (column 1 math mode for the commands, column 3 in \texttt with a leading backslash for the code) were decidedly handy. I've only just come across it thanks to \span. – MickG Sep 28 '14 at 12:43
• @MickG you can specify columns as math mode and texttt using tabular (array package version) no need for \halign for that. – David Carlisle Sep 30 '14 at 23:00
• @DavidCarlisle I'll look into that sooner or later, though I'd never heard of that package. – MickG Oct 1 '14 at 6:38

The \halign builds horizontal boxes which are put on the surrounding vertical list, there are insensitive to the \leftskip and \rightskip obeyed by the paragraph builder.

You can try to center using this:

\documentclass{article}

\begin{document}
\halign{\vrule \hfil # \hfil & \hfil # \hfil \vrule \cr
a & b \cr\noalign{\hrule}
c & d \cr\noalign{\hrule}
}

\tabskip 0pt plus 1000pt minus 1000pt
\halign to \hsize{\tabskip0pt\vrule \hfil # \hfil & \hfil # \hfil \vrule
\tabskip 0pt plus 1000pt minus 1000pt \cr
a & b \cr\noalign{\hrule}
c & d \cr\noalign{\hrule}
}

\end{document}


However, the \hrule extends the whole \hsize width.

We can put the \halign in a \vbox.

\bigskip

\centering
\noindent\vbox{\halign{\vrule \hfil # \hfil & \hfil # \hfil \vrule \cr
a & b \cr\noalign{\hrule}
c & d \cr\noalign{\hrule}
}}


• OK that works. It is curious though that only \centering or only \vbox are not enough. Why is that? – MickG Sep 27 '14 at 21:04
• Basically, \centering is \rightskip \@flushglue \leftskip \@flushglue plus some more stuff. But these skips are obeyed by the paragraph builder when it breaks a paragraph into lines. The \halign is another way to create horizontal lines, it has no reason to obey \leftskip and \rightskip. With a \vbox we then trigger the paragraph builder. – user4686 Sep 27 '14 at 21:06
• I just tried it on more complex tables, and it doesn't seem to work. But I'm afraid posting the actual problem means posting too much code :). – MickG Sep 27 '14 at 21:33
• In my previous comment: "with a \noindent\vbox we trigger the paragraph builder" was meant (a \vbox by itself does not switch to horizontal mode; in LaTeX on the other hand all box commands such as \usebox, \parbox, ... force to leave vertical mode). You don't say what did not work with more complex tables. The advantage of \halign is to be able to spread over multiple pages. As soon as you put it in a box (like tabular does) you can't if not later "undoing" the box to extract from it its lines. – user4686 Sep 28 '14 at 9:55