How to simply align table content both vertically and horizontally

My table needs to align its content both vertically and horizontally.

Here is the code:

\documentclass[twocolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{booktabs, array}
\usepackage{lipsum}
\begin{document}
\begin{table*}
\centering
\begin{tabular}{>{\centering\arraybackslash}m{1cm}>{\centering\arraybackslash}m{1cm}}
\toprule 1 & 2 \\ \midrule 3 & 4 \\ \bottomrule
\end{tabular}
\caption{table 1}
\end{table*}

\lipsum[1-15] % filler text
\end{document}


To the best of my understanding, m should align the contents vertically and these >{\centering\arraybackslash} segments should align it horizontally. However, if you measure the space above the digits and the space beneath them, you will see that there is more space beneath them.

• align cell content both horizontally and vertically, and
• make column width scale automatically (with its content).

I found many similar questions here, but none of them actually addresses the problem on the elementary level.

• Regarding "make column width scale automatically (with its content)." : wh not use a simple c type column? Sep 19 at 16:45
• " if you measure the space above the digits and the space beneath them, you will see that there is more space beneath them" this valid only in case, if in text you haven't letters g, p, y ... Sep 19 at 17:06
• I believe \toprule, \midrule and \bottomrule all add varying amounts of space above and below. Try \hline instead. Sep 19 at 19:50

The classic tool is the cellspace package: you prefix the column specifier with the letter S by default (or C if you load siunitx, or whatever letter you please with the [columntype=some letter] loading option):

\documentclass[twocolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{booktabs, array}
\usepackage{lipsum}
\usepackage{cellspace}
\setlength{\cellspacetoplimit}{4pt}
\setlength{\cellspacebottomlimit}{4pt}

\begin{document}
\begin{table*}
\centering
\begin{tabular}{>{\centering\arraybackslash}S{m{1cm}}>{\centering\arraybackslash}S{m{1cm}}}
\toprule 1 & 2 \\ \midrule 3 & 4 \\ \bottomrule
\end{tabular}
\caption{table 1}
\end{table*}

\lipsum[1-15] % filler text

\end{document}


If you are in a hurry

\documentclass[twocolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{booktabs, array}
\usepackage{lipsum}
\begin{document}

\begin{table*}
\centering
\begin{tblr}{colspec={Q[c,m]Q[c,m]},rows={rowsep=4pt},stretch=0}
\toprule
11 & 2 \\
\midrule
3 & 4444444 \\
\bottomrule
\end{tblr}
\caption{tblr with numbers}
\end{table*}

\lipsum[1-15] % filler text
\end{document}


Note 1: I've used a different package: tabularray

About "align cell content both horizontally and vertically":

The tabularray package has a nice way to centralize everything. But as far as I know, it considers that the line to have a full height (with ascenders AND descenders) to perform the alignment. (Mico talks better about it)

You can see this in the following two examples stolen from the package documentation:

\documentclass[twocolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{booktabs, array}
\usepackage{lipsum}
\begin{document}

\begin{table*}
\centering
\begin{tblr}{lccr}
\hline
Alpha & Beta & Gamma & Delta \\
\hline
Epsilon & Zeta & Eta & Theta \\
\hline
Iota & Kappa & Lambda & Mu \\
\hline
\end{tblr}
\caption{tblr with text}
\end{table*}

\begin{table*}
\centering
\begin{tabular}{lccr}
\hline
Alpha & Beta & Gamma & Delta \\
\hline
Epsilon & Zeta & Eta & Theta \\
\hline
Iota & Kappa & Lambda & Mu \\
\hline
\end{tabular}
\caption{tabular with text}
\end{table*}

\lipsum[1-15] % filler text
\end{document}


However, when you only use numbers (As Mico said, numbers have ascenders but not descenders) you get this, on which the tblr works even worse than tabular:

\begin{table*}
\centering
\begin{tblr}{Q[c,m,1cm]Q[c,m,1cm]}
\toprule
1 & 2 \\
\midrule
3 & 4 \\
\bottomrule
\end{tblr}
\caption{tblr with numbers}
\end{table*}

\begin{table*}
\centering
\begin{tabular}{>{\centering\arraybackslash}m{1cm}>{\centering\arraybackslash}m{1cm}}
\toprule 1 & 2 \\ \midrule 3 & 4 \\ \bottomrule
\end{tabular}
\caption{tabular with numbers}
\end{table*}


Option 1 (this one is better)

Thanks to L.J.R.'s suggestion we can use stretch=0. I also used rowsep=4pt to make the table look less squished.

\begin{table*}
\centering
\begin{tblr}{colspec={Q[c,m,1cm]Q[c,m,1cm]},stretch=0}
\toprule
1 & 2 \\
\midrule
3 & 4 \\
\bottomrule
\end{tblr}
\caption{tblr without rowsep=4pt}
\end{table*}

\begin{table*}
\centering
\begin{tblr}{colspec={Q[c,m,1cm]Q[c,m,1cm]},stretch=0,rows={rowsep=4pt}}
\toprule
1 & 2 \\
\midrule
3 & 4 \\
\bottomrule
\end{tblr}
\caption{tblr with rowsep=4pt}
\end{table*}


Option 2 (old solution)

You can manually fix this problem very easily by using abovesep+ to add space above text like so:

\begin{table*}
\centering
\begin{tblr}{colspec={Q[c,m,1cm]Q[c,m,1cm]},rows={abovesep+=2pt}}
\toprule
1 & 2 \\
\midrule
3 & 4 \\
\bottomrule
\end{tblr}
\caption{tblr with numbers}
\end{table*}

\begin{table*}
\centering
\begin{tabular}{>{\centering\arraybackslash}m{1cm}>{\centering\arraybackslash}m{1cm}}
\toprule 1 & 2 \\ \midrule 3 & 4 \\ \bottomrule
\end{tabular}
\caption{tabular with numbers}
\end{table*}


About "make column width scale automatically (with its content)":

Not setting a width to Q column would solve this issue, wouldn't it?

\documentclass[twocolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{booktabs, array}
\usepackage{lipsum}
\begin{document}

\begin{table*}
\centering
\begin{tblr}{colspec={Q[c,m]|Q[c,m]},stretch=0,rows={rowsep=4pt}}
\toprule
1 & 2 \\
\midrule
3 & 4 \\
\bottomrule
\end{tblr}
\caption{tblr with numbers}
\end{table*}

\begin{table*}
\centering
\begin{tblr}{colspec={Q[c,m]|Q[c,m]},stretch=0,rows={rowsep=4pt}}
\toprule
11 & 2 \\
\midrule
3 & 4444 \\
\bottomrule
\end{tblr}
\caption{tblr with numbers}
\end{table*}

\lipsum[1-15] % filler text
\end{document}


Problem when you mix number and letters

The problem reappears when you mix letters and numbers (see Table 1 below). It's important to note that the alignment is being performed as if each character in the same row had the same total height as a box formed by them all. So a 3 and a p will be aligned as if they were 3p, which causes a visual misalignment.

Note that 3 has no depth and p has less height than 3. Here is a good discussion on this topic of height and depth.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{booktabs,array}

\newlength\height
\newlength\depth
\newlength\totalheight

\newcommand{\RULE}[1]{%
\settoheight{\height}{#1}%
\settodepth{\depth}{#1}%
\setlength\totalheight{\dimexpr\height+\depth\relax}%
\rule[-\depth]{0.1pt}{\totalheight}#1\rule[-\depth]{0.1pt}{\totalheight}%
}

\newcommand{\STH}[1]{%
\settoheight{\height}{#1}%
\settodepth{\depth}{#1}%
\setlength\totalheight{\dimexpr\height+\depth\relax}%
height of \textcolor{red}{#1}: \textcolor{blue!70!gray}{\the\height}\par
depth of \textcolor{red}{#1}: \textcolor{blue!70!gray}{\the\depth}\par
total height of \textcolor{red}{#1}: \textcolor{blue!70!gray}{\the\totalheight}\par
\vspace{8pt}
}

\begin{document}

\STH{3}
\STH{p}
\STH{3p}

\begin{table*}[t]
\centering
\begin{tblr}{colspec={Q[c,m]Q[c,m]},stretch=0}
\toprule
1 & 2 \\
\midrule
AAAA & 6 \\
\midrule
g & pppp \\
\midrule
33 & pppp \\
\midrule
\RULE{3} & \RULE{p} \\
\midrule
\RULE{\vphantom{3p}3} &  \RULE{\vphantom{3p}p}\\
\midrule
\RULE{3p} &  \RULE{3p}\\
\bottomrule
\end{tblr}
\caption{tblr with numbers and letters}
\end{table*}

\end{document}

• What the OP wants is removing the strut. Setting stretch=0 will do the trick for any case. Sep 20 at 12:31
• Thank you @L.J.R.! You are the package creator, so I have no choice but to learn from you. I've updated my answer to include your suggestion and also added an issue that arises when we mix numbers and letters. If you have time to read my answer, please let me know whether you agree with everything I have said so that I can correct the remaining mistakes. Feel free to modify my answer any way you want. Sep 20 at 15:40
• The result is correct when you mix numbers and letters: the space above 3 is the same as the space below p. Sep 21 at 0:10
• @L.J.R. Oh yes, this is theoretically correct, yes. All the characters in the same row are being considered to have the same total height, hence they are aligned relative to this invisible box generated by 3p. However I think the OP wanted a vertical alignment in visual way, i. e., as if the 3 didn't have depth and the p didn't have as much height as 3. I will expand the problem section in my answer to make that clear to future readers. Sep 21 at 16:57

I'd like to question your claim that the m column type doesn't center its contents vertically.

Your claim appears to be based in part on a very specific choice for the contents of the cells in your test table: the characters you chose have only ascenders (lines that rise above the x-line) but no descenders (lines that fall below the baseline). Once you relax this extreme choice, you'll find that the vertical whitespace between thr upper \midrule and the tips of the ascendersis very close to the amount of vertical whitespace between the bottoms of the descenders and the lower\midrule.

You also wrote:

if you measure the space above the digits and the space beneath them, you will see that there is more space beneath them.

Again, that's true only if you only use characters that have ascenders and no descenders. For sure, if you were to use characters that have neither ascenders nor descenders -- acemnorsuvwxz -- your finding would have to be reversed.

In short: do learn to trust LaTeX to get the vertical alignment right. :-)

\documentclass[twocolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{booktabs, array}
\begin{document}
\begin{table}
\centering
\begin{tabular}{*{2}{>{\centering\arraybackslash}m{3cm}}}
\midrule
pqyhbkpqy & acemnorsuvwxz \\
\midrule
acemnorsuvwxz & pqyhbkpqy \\
\midrule
\end{tabular}
\end{table}
\end{document}

• That makes sense. However, it would be great if I could vertically align content in a dynamic fashion; in the sense that first the content is placed and then centering is applied. That way both, e.g., l and g` can be centered.
– foki
Sep 20 at 13:24