# Vertical alignment in table: m-column, row size - problem in last column

Unfortunatly, I have a problem with m-columns (array package) in tables with adjusted row height. Somehow in the last column (only there) the text is not centered vertically.

Check it out:

\documentclass{article}
\usepackage{array}

\begin{document}

\begin{tabular}{|m{0.18cm}|m{0.18cm}|m{0.18cm}|}
\hline
a & b & c  \\[2ex]
\hline
0 & 0 & 0  \\
\hline
\end{tabular}

\end{document}

-

In my opinion, it is a bug and should be reported. Tweak for the impatient: add one extra column with zero width and no padding. Remember to pre-pend \\ with & on the problematic lines!

\documentclass{article}
\usepackage{array}

\begin{document}

\begin{tabular}{|m{0.18cm}|m{0.18cm}|m{0.18cm}|@{}m{0pt}@{}}
\hline
a & b & c &\\[2ex]
\hline
0 & 0 & 0 \\
\hline
\end{tabular}

\end{document}

-
Do you know if the bug was reported? How is it's status? –  student Oct 18 '12 at 17:36
@student I was not reporting it so I have no clue. –  tohecz Oct 18 '12 at 17:37
Let's be clare about the fact that the above is not resolving the bug but actually providing a solution to something else: in fact it makes use of the bug with the result that the space from \[2ex] appears to be distributed above and below the row. However, the correct result from the original input would be that all cells align in the middle and since they are all just one line high the are actually all at the top and the space from \[2ex] appears below (as always). –  Frank Mittelbach Sep 10 at 13:59

The question as well as the answer by @tohecz indicate that there is at least one fundamental misconception about what the preamble tokens "m", "b", etc do and how this relates to \\ and its optional argument.

The "m" token is not centering its material vertically in the available space!

The tokens "c", "l" and "r" produce horizontal cells (one line high) and their alignment point vertically is just the baseline of each cell. Now "p", "m" and "b" generate cells of a certain width and possibly several lines. Their vertical alignment is the first line, the middle of the box and the bottom line, respectively. So if we modify the example a bit and run:

\begin{tabular}{|p{0.18cm}|m{0.18cm}|b{0.18cm}|l|}
\hline
a\newline a & b\newline b & c\newline c\newline c& d \\
\hline
\end{tabular}


and what we get is

So this is all positioned relative to the baseline of the cell containing "d".

Now the optional argument of \\ only extends the space from the alignment point downwards it is not extending the size of the actual cells. Furthermore it is not actually adding this space but only making sure that there is at least that amount of space to the next row. So for example, in the above case \\[2ex] would have no effect because the cell in the first column goes further down than this.

So coming back to the original question and its input: because each cell has only a single line they should all line up but the "m" would not have the effect of centering the content in the available space. Instead the extra space requested by \\[2ex] would go after it (or should ... that's the bug).

So lets add an "l" column to avoid the bug and see what happens:

\begin{tabular}{|m{0.18cm}|m{0.18cm}|m{0.18cm}|l|}
\hline
a & b & c & d \\[2ex]
\hline
a\newline a & b & c & d \\[2ex]
\hline
\end{tabular}


Result is

The first row shows that "m" and "l" sit side by side if the "m" has only a single line inside and that the 2ex is between the baseline and the next row.

The second line has an "m" with 2 lines inside and there you see again that the 2ex goes from the row baseline to the next row and "m" is not vertically centered either.

So the suggestion to use an extra (kind of hidden row) like

\begin{tabular}{|m{0.18cm}|m{0.18cm}|m{0.18cm}|@{}m{0pt}@{}}
\hline
a & b & c &             x\\[4ex]   % x normally being a space
\hline
a\newline a & b & c &   x\\[4ex]
\hline
\end{tabular}


is actually making use of the current bug, i.e., the "space" in that hidden question is actually pushed upwards so that the visible rows now appear more or less centered (which I made visible by putting in an "x" above):

So the moment this would get fixed the above trick no longer works.

## So what is the bug?

The issue is very subtle. To make a table with rules work it is not possible to vertically skip downwards on \\[2ex], instead what happens is that in one of the row an invisible rule/box is placed that has a depth extending the normal depth by 2ex. If you don't do this then any vertical rule gets a disruption in places where you add additional vertical space.

The downside of this is, that if a row has an unusual depth, any such exstra space may come out short because it is measured in relation to the "normal" depth.

In addition and that is the "bug" in array putting this invisual strut at the end of the material in the last row, simply goes wrong for m-columns as they are vertically centered. Thus here you see the "c" moving upwards as the strut ends up in some sort of $\vcenter{... c \strut}$ instead of $\vcenter{... c}$\strut.

The reason for this is the strange behavior of the underlying \halign mechanism of TeX that is used to build tables: when we reach \\[2ex] LaTeX has processed $\vcenter{... c but not yet seen the remaining material that forms the column, i.e., }$.

So \\[ex] calculates and adds the strut and then tells TeX that the column is finished (using \crinternally) and that results in TeX copying the remaining part of the column template (}$...plus space and rule) into the input stream and bingo you end up with the strut inside vcenter. A possible fix would be to delay the strut placement to ensure that this happens only in the right part of the column template. That in turn is a bit tricky as by that time scoping will have changed values back etc. So this needs to be a global operation. \documentclass{article} \usepackage{array} \makeatletter \def\@classz{\@classx \@tempcnta \count@ \prepnext@tok \@addtopreamble{\ifcase \@chnum \hfil \d@llarbegin \insert@column \d@llarend\fmi@fix \hfil \or \hskip1sp\d@llarbegin \insert@column \d@llarend\fmi@fix \hfil \or \hfil\hskip1sp\d@llarbegin \insert@column \d@llarend\fmi@fix \or$\vcenter
\@startpbox{\@nextchar}\insert@column \@endpbox \$\fmi@fix
\or
\vtop \@startpbox{\@nextchar}\insert@column \@endpbox\fmi@fix \or
\vbox \@startpbox{\@nextchar}\insert@column \@endpbox\fmi@fix
\fi}\prepnext@tok}

\def\@mkpream#1{\gdef\@preamble{}\@lastchclass 4 \@firstamptrue
\let\@sharp\relax \let\@startpbox\relax \let\@endpbox\relax
\let\fmi@fix\relax
\@temptokena{#1}\@tempswatrue
\@whilesw\if@tempswa\fi{\@tempswafalse\the\NC@list}%
\count@\m@ne
\let\the@toks\relax
\prepnext@tok
\expandafter \@tfor \expandafter \@nextchar
\expandafter :\expandafter =\the\@temptokena \do
{\@testpach
\ifcase \@chclass \@classz \or \@classi \or \@classii
\or \save@decl \or \or \@classv \or \@classvi
\or \@classvii \or \@classviii
\or \@classx
\or \@classx \fi
\@lastchclass\@chclass}%
\ifcase\@lastchclass
\@acol \or
\or
\@acol \or
\@preamerr \thr@@ \or
\or
\else  \@preamerr \@ne \fi
\def\the@toks{\the\toks}}

\def\@xargarraycr#1{\gdef\fmi@fix
\vrule \@depth\@tempdima \@width\z@\global\let\fmi@fix\relax}\cr}
\let\fmi@fix\relax

\makeatother

\begin{document}

\begin{tabular}{|m{0.18cm}|m{0.18cm}|}
\hline
a&c \\[2ex]
\hline
0& 0  \\
\hline
\end{tabular}

\end{document}


As I said this is rather delicate so I'm not sure it is safe to make that type of change without breaking a lot of other stuff (after all array` is a really old package (25+ years) which is used quite a lot and that issue is in there from the beginning.

Anyway with the above change we now get:

which is what we should but perhaps not what people hoped when they thought they specify an "m" column.

-
in this specific case, a and c are not vertically aligned... –  Maïeul Sep 9 at 9:15
@Maïeul meaning what? after applying the above patch? It worked when I ran the file --- however, as I said above this is an area where it is nearly impossible to change things without breaking something else –  Frank Mittelbach Sep 9 at 11:23
@Maïeul they are not vertically centered in the whole space, no. But this is not what "m" does. I rewrote the answer to make all this and the interface clearer –  Frank Mittelbach Sep 11 at 15:08
yes, that is clearer... –  Maïeul Sep 11 at 15:11
thank a lot.. there is some time different between what we need and what we understand LaTeX does... –  Maïeul Sep 11 at 15:11