Vertical alignment in table: m-column, row size - problem in last column
up vote
38
down vote
favorite
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}
tables vertical-alignment line-spacing
add a comment |
up vote
38
down vote
favorite
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}
tables vertical-alignment line-spacing
add a comment |
up vote
38
down vote
favorite
up vote
38
down vote
favorite
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}
tables vertical-alignment line-spacing
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}
tables vertical-alignment line-spacing
tables vertical-alignment line-spacing
edited Jun 10 '17 at 14:05
David Carlisle
480k3811121847
480k3811121847
asked Aug 25 '12 at 12:50
Stefe Klauou
4591413
4591413
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
34
down vote
accepted
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.
– boycott.se - yo'
Oct 18 '12 at 17:37
3
latex-project.org/cgi-bin/ltxbugs2html?pr=tools%2F4246
– David Carlisle
May 15 '13 at 13:01
2
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 '14 at 13:59
add a comment |
up vote
26
down vote
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
anewline a & bnewline b & cnewline cnewline 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 let's 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
anewline 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
anewline 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 cr
internally) 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@llarendfmi@fix hfil or
hskip1spd@llarbegin insert@column d@llarendfmi@fix hfil or
hfilhskip1spd@llarbegin insert@column d@llarendfmi@fix or
$vcenter
@startpbox{@nextchar}insert@column @endpbox $fmi@fix
or
vtop @startpbox{@nextchar}insert@column @endpboxfmi@fix or
vbox @startpbox{@nextchar}insert@column @endpboxfmi@fix
fi}prepnext@tok}
def@mkpream#1{gdef@preamble{}@lastchclass 4 @firstamptrue
let@sharprelax let@startpboxrelax let@endpboxrelax
letfmi@fixrelax
@temptokena{#1}@tempswatrue
@whileswif@tempswafi{@tempswafalsetheNC@list}%
count@m@ne
letthe@toksrelax
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
@preamerr tw@ @addtopreamble@sharp or
or
else @preamerr @ne fi
defthe@toks{thetoks}}
def@xargarraycr#1{gdeffmi@fix
{@tempdima #1advance@tempdima dp@arstrutbox
vrule @depth@tempdima @widthz@globalletfmi@fixrelax}cr}
letfmi@fixrelax
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.
Update
As of 2018-04 release of LaTeX (or even one release earlier) the actual bug has now been corrected as outline above. That means (unfortunately) that the trick suggested above and marked as the correct answer is not longer working, but as I explained it was based on a wrong assumption of what the specification of "m" is.
in this specific case, a and c are not vertically aligned...
– Maïeul
Sep 9 '14 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 '14 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 '14 at 15:08
yes, that is clearer...
– Maïeul
Sep 11 '14 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 '14 at 15:11
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
34
down vote
accepted
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.
– boycott.se - yo'
Oct 18 '12 at 17:37
3
latex-project.org/cgi-bin/ltxbugs2html?pr=tools%2F4246
– David Carlisle
May 15 '13 at 13:01
2
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 '14 at 13:59
add a comment |
up vote
34
down vote
accepted
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.
– boycott.se - yo'
Oct 18 '12 at 17:37
3
latex-project.org/cgi-bin/ltxbugs2html?pr=tools%2F4246
– David Carlisle
May 15 '13 at 13:01
2
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 '14 at 13:59
add a comment |
up vote
34
down vote
accepted
up vote
34
down vote
accepted
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}
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}
edited Jul 15 '17 at 15:33
David Carlisle
480k3811121847
480k3811121847
answered Aug 25 '12 at 15:29
boycott.se - yo'
39k8122231
39k8122231
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.
– boycott.se - yo'
Oct 18 '12 at 17:37
3
latex-project.org/cgi-bin/ltxbugs2html?pr=tools%2F4246
– David Carlisle
May 15 '13 at 13:01
2
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 '14 at 13:59
add a comment |
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.
– boycott.se - yo'
Oct 18 '12 at 17:37
3
latex-project.org/cgi-bin/ltxbugs2html?pr=tools%2F4246
– David Carlisle
May 15 '13 at 13:01
2
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 '14 at 13:59
Do you know if the bug was reported? How is it's status?
– student
Oct 18 '12 at 17:36
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.
– boycott.se - yo'
Oct 18 '12 at 17:37
@student I was not reporting it so I have no clue.
– boycott.se - yo'
Oct 18 '12 at 17:37
3
3
latex-project.org/cgi-bin/ltxbugs2html?pr=tools%2F4246
– David Carlisle
May 15 '13 at 13:01
latex-project.org/cgi-bin/ltxbugs2html?pr=tools%2F4246
– David Carlisle
May 15 '13 at 13:01
2
2
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 '14 at 13:59
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 '14 at 13:59
add a comment |
up vote
26
down vote
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
anewline a & bnewline b & cnewline cnewline 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 let's 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
anewline 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
anewline 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 cr
internally) 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@llarendfmi@fix hfil or
hskip1spd@llarbegin insert@column d@llarendfmi@fix hfil or
hfilhskip1spd@llarbegin insert@column d@llarendfmi@fix or
$vcenter
@startpbox{@nextchar}insert@column @endpbox $fmi@fix
or
vtop @startpbox{@nextchar}insert@column @endpboxfmi@fix or
vbox @startpbox{@nextchar}insert@column @endpboxfmi@fix
fi}prepnext@tok}
def@mkpream#1{gdef@preamble{}@lastchclass 4 @firstamptrue
let@sharprelax let@startpboxrelax let@endpboxrelax
letfmi@fixrelax
@temptokena{#1}@tempswatrue
@whileswif@tempswafi{@tempswafalsetheNC@list}%
count@m@ne
letthe@toksrelax
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
@preamerr tw@ @addtopreamble@sharp or
or
else @preamerr @ne fi
defthe@toks{thetoks}}
def@xargarraycr#1{gdeffmi@fix
{@tempdima #1advance@tempdima dp@arstrutbox
vrule @depth@tempdima @widthz@globalletfmi@fixrelax}cr}
letfmi@fixrelax
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.
Update
As of 2018-04 release of LaTeX (or even one release earlier) the actual bug has now been corrected as outline above. That means (unfortunately) that the trick suggested above and marked as the correct answer is not longer working, but as I explained it was based on a wrong assumption of what the specification of "m" is.
in this specific case, a and c are not vertically aligned...
– Maïeul
Sep 9 '14 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 '14 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 '14 at 15:08
yes, that is clearer...
– Maïeul
Sep 11 '14 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 '14 at 15:11
add a comment |
up vote
26
down vote
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
anewline a & bnewline b & cnewline cnewline 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 let's 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
anewline 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
anewline 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 cr
internally) 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@llarendfmi@fix hfil or
hskip1spd@llarbegin insert@column d@llarendfmi@fix hfil or
hfilhskip1spd@llarbegin insert@column d@llarendfmi@fix or
$vcenter
@startpbox{@nextchar}insert@column @endpbox $fmi@fix
or
vtop @startpbox{@nextchar}insert@column @endpboxfmi@fix or
vbox @startpbox{@nextchar}insert@column @endpboxfmi@fix
fi}prepnext@tok}
def@mkpream#1{gdef@preamble{}@lastchclass 4 @firstamptrue
let@sharprelax let@startpboxrelax let@endpboxrelax
letfmi@fixrelax
@temptokena{#1}@tempswatrue
@whileswif@tempswafi{@tempswafalsetheNC@list}%
count@m@ne
letthe@toksrelax
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
@preamerr tw@ @addtopreamble@sharp or
or
else @preamerr @ne fi
defthe@toks{thetoks}}
def@xargarraycr#1{gdeffmi@fix
{@tempdima #1advance@tempdima dp@arstrutbox
vrule @depth@tempdima @widthz@globalletfmi@fixrelax}cr}
letfmi@fixrelax
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.
Update
As of 2018-04 release of LaTeX (or even one release earlier) the actual bug has now been corrected as outline above. That means (unfortunately) that the trick suggested above and marked as the correct answer is not longer working, but as I explained it was based on a wrong assumption of what the specification of "m" is.
in this specific case, a and c are not vertically aligned...
– Maïeul
Sep 9 '14 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 '14 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 '14 at 15:08
yes, that is clearer...
– Maïeul
Sep 11 '14 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 '14 at 15:11
add a comment |
up vote
26
down vote
up vote
26
down vote
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
anewline a & bnewline b & cnewline cnewline 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 let's 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
anewline 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
anewline 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 cr
internally) 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@llarendfmi@fix hfil or
hskip1spd@llarbegin insert@column d@llarendfmi@fix hfil or
hfilhskip1spd@llarbegin insert@column d@llarendfmi@fix or
$vcenter
@startpbox{@nextchar}insert@column @endpbox $fmi@fix
or
vtop @startpbox{@nextchar}insert@column @endpboxfmi@fix or
vbox @startpbox{@nextchar}insert@column @endpboxfmi@fix
fi}prepnext@tok}
def@mkpream#1{gdef@preamble{}@lastchclass 4 @firstamptrue
let@sharprelax let@startpboxrelax let@endpboxrelax
letfmi@fixrelax
@temptokena{#1}@tempswatrue
@whileswif@tempswafi{@tempswafalsetheNC@list}%
count@m@ne
letthe@toksrelax
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
@preamerr tw@ @addtopreamble@sharp or
or
else @preamerr @ne fi
defthe@toks{thetoks}}
def@xargarraycr#1{gdeffmi@fix
{@tempdima #1advance@tempdima dp@arstrutbox
vrule @depth@tempdima @widthz@globalletfmi@fixrelax}cr}
letfmi@fixrelax
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.
Update
As of 2018-04 release of LaTeX (or even one release earlier) the actual bug has now been corrected as outline above. That means (unfortunately) that the trick suggested above and marked as the correct answer is not longer working, but as I explained it was based on a wrong assumption of what the specification of "m" is.
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
anewline a & bnewline b & cnewline cnewline 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 let's 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
anewline 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
anewline 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 cr
internally) 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@llarendfmi@fix hfil or
hskip1spd@llarbegin insert@column d@llarendfmi@fix hfil or
hfilhskip1spd@llarbegin insert@column d@llarendfmi@fix or
$vcenter
@startpbox{@nextchar}insert@column @endpbox $fmi@fix
or
vtop @startpbox{@nextchar}insert@column @endpboxfmi@fix or
vbox @startpbox{@nextchar}insert@column @endpboxfmi@fix
fi}prepnext@tok}
def@mkpream#1{gdef@preamble{}@lastchclass 4 @firstamptrue
let@sharprelax let@startpboxrelax let@endpboxrelax
letfmi@fixrelax
@temptokena{#1}@tempswatrue
@whileswif@tempswafi{@tempswafalsetheNC@list}%
count@m@ne
letthe@toksrelax
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
@preamerr tw@ @addtopreamble@sharp or
or
else @preamerr @ne fi
defthe@toks{thetoks}}
def@xargarraycr#1{gdeffmi@fix
{@tempdima #1advance@tempdima dp@arstrutbox
vrule @depth@tempdima @widthz@globalletfmi@fixrelax}cr}
letfmi@fixrelax
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.
Update
As of 2018-04 release of LaTeX (or even one release earlier) the actual bug has now been corrected as outline above. That means (unfortunately) that the trick suggested above and marked as the correct answer is not longer working, but as I explained it was based on a wrong assumption of what the specification of "m" is.
edited 3 hours ago
answered Apr 29 '14 at 9:15
Frank Mittelbach
60k5175247
60k5175247
in this specific case, a and c are not vertically aligned...
– Maïeul
Sep 9 '14 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 '14 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 '14 at 15:08
yes, that is clearer...
– Maïeul
Sep 11 '14 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 '14 at 15:11
add a comment |
in this specific case, a and c are not vertically aligned...
– Maïeul
Sep 9 '14 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 '14 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 '14 at 15:08
yes, that is clearer...
– Maïeul
Sep 11 '14 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 '14 at 15:11
in this specific case, a and c are not vertically aligned...
– Maïeul
Sep 9 '14 at 9:15
in this specific case, a and c are not vertically aligned...
– Maïeul
Sep 9 '14 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 '14 at 11:23
@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 '14 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 '14 at 15:08
@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 '14 at 15:08
yes, that is clearer...
– Maïeul
Sep 11 '14 at 15:11
yes, that is clearer...
– Maïeul
Sep 11 '14 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 '14 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 '14 at 15:11
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f68732%2fvertical-alignment-in-table-m-column-row-size-problem-in-last-column%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown