190

I have a simple table as follows:

\begin{table*}
    \centering
    \begin{tabular}{|l|c|c|c|c|p{2in}|}
    ...
    ...
    \end{tabular}
    \caption{The factors the camera solver depends on to evaluate the rules.}
    \label{table:factors}
\end{table*}

How is it possible to vertically-center the text of the cells?

6
  • 4
    This earlier question might be of help to you.
    – morbusg
    Dec 16, 2010 at 12:34
  • 5
    Looking closer at your example, I realize you obviously have the array package loaded. p{...} aligns the content toward the top, m{...} aligns the content toward the center, while b{...} aligns it toward the bottom.
    – Jimi Oke
    Dec 17, 2010 at 23:19
  • 2
    @Jimi: the example works even without array. The p specifier is standard.
    – Stefan Kottwitz
    Dec 18, 2010 at 15:35
  • 2
    Question, actually. How in the world would a person who knows nothing about code go about this? I'm drowning in information, here.
    – user44066
    Jan 12, 2014 at 23:33
  • 1
    @Amy it's not as bad as it looks. You can just copy the code into your document and see if it works. After some time you will get used to Latex code more and more. I would start with the small things first by making tables in an -- for you -- acceptable format, without worrying too much about perfection, which can be done later.
    – TomM
    Jan 13, 2014 at 0:16

8 Answers 8

48

Edit: The existence of this new answer has made my answer now obsolete and embarrassing. Please proceed to the new answer and vote it up.

enter image description here

\documentclass{article}
\usepackage[a4paper,vmargin=2cm,hmargin=1cm,showframe]{geometry}
\usepackage[demo]{graphicx}
\usepackage[table]{xcolor}
\usepackage{array}
\usepackage{longtable}

\parindent=0pt

\def\correction#1{%
    \abovedisplayshortskip=#1\baselineskip\relax\belowdisplayshortskip=#1\baselineskip\relax%
    \abovedisplayskip=#1\baselineskip\relax\belowdisplayskip=#1\baselineskip\relax}

\arrayrulewidth=1pt\relax
\tabcolsep=5pt\relax
\arrayrulecolor{red}
\fboxsep=\tabcolsep\relax
\fboxrule=\arrayrulewidth\relax

\newcolumntype{A}[2]{%
    >{\minipage{\dimexpr#1\linewidth-2\tabcolsep-#2\arrayrulewidth\relax}\vspace\tabcolsep}%
    c<{\vspace\tabcolsep\endminipage}}
    

\newenvironment{Table}[4]{%
    \longtable{%
        |A{#1}{1.5}% for figure
        |>{\centering$\displaystyle}A{#2}{1}<{$}% for inline equation
        |>{\correction{-1}\strut\[}A{#3}{1}<{\]\strut}% for displayed equation
        |>{\centering}A{#4}{1.5}% for text
        |}\hline\ignorespaces}{%
    \endlongtable\ignorespacesafterend}

\newcommand{\dummy}{%
    It is practically a big lie that \LaTeX\ 
    makes you focus on the content without
    bothering about the layout.}


\newcommand{\Row}{%
    \includegraphics[width=\linewidth]{newton}&
    \frac{a+b}{a-b}=0&
    \int_a^b f(x)\, \textrm{d}x=\frac{b-a}{b+a}&
    \fcolorbox{cyan}{yellow}{\parbox{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}{\dummy}}
    \tabularnewline\hline}

\begin{document}
\begin{Table}{0.25}{0.25}{0.25}{0.25}
\Row
\Row
\end{Table}

\def\x{\centering$\displaystyle\int_a^bf(x)\,\textrm{d}x=\frac{a-b}{a+b}$}

\longtable{|A{0.2}{1.5}*2{|A{0.25}{1}}|A{0.3}{1.5}|}\hline
\x & \x & \multicolumn{2}{A{0.55}{1.5}|}{\x} \tabularnewline\hline
\multicolumn{2}{|A{0.45}{1.5}|}{\x} & \x & \x\tabularnewline\hline 
\x & \multicolumn{2}{A{0.5}{1}|}{\x} & \x\tabularnewline\hline 
\multicolumn{4}{|A{1}{2}|}{\x}\tabularnewline\hline 
\endlongtable
\end{document}
8
  • 127
    Your solution is working absolutely fine, but isn't there a simpler solution? Aligning contents vertically feels time like simpler than the proposed solution.
    – Rafid
    Dec 16, 2010 at 19:42
  • 54
    This answer should have some explaining text so it is easier to understand.
    – dinosaur
    Sep 15, 2016 at 23:20
  • 64
    Unfortunately, this kind of answer is what may scare people away from LaTeX.
    – gerrit
    Jul 14, 2018 at 20:24
  • 35
    This kind of answer shows that LaTeX is just plain bad at tables. It's great at many things, but doing anything with tables is an overcomplicated mess and a huge distraction from what I'm actually trying to do, every time. Gah. Jul 26, 2018 at 22:27
  • 17
    This can't be the best solution. I expected including a package and just adding something like \vcenter to the cell of choice. This is intended as a critique on LaTeX, not the answer in itself (for which I thank you).
    – Jan M.
    Nov 15, 2018 at 14:29
151

One easy way to this would be to use the array package, specifying your column width with m{...}. For example:

\begin{tabular}{ m{4cm} m{1cm} }
   ... & ... \\end{tabular}

will give you a four centimeter-long column and a one centimeter-long column. In each cell, the contents will be vertically aligned to the center. Note, however, that the cell contents will be horizontally aligned left. If you also want to align all the cell contents toward the center in a horizontal sense, then you could do something like this:

\begin{tabular}{ >{\centering\arraybackslash} m{4cm} >{\centering\arraybackslash} m{4cm} }
   ... & ... \\end{tabular}

The point of \arraybackslash is to return \\ to its original meaning because the \centering command alters this and could possibly give you a noalign error during compilation.

If you have several columns and do not want your source to look cluttered, you could define new columns before your tabular environment, for example:

\newcolumntype{C}{ >{\centering\arraybackslash} m{4cm} }
\newcolumntype{D}{ >{\centering\arraybackslash} m{1cm} }
\begin{tabular}{ C D }
   ... & ... \\end{tabular}

There is a lot of useful information on tables in the wiki LaTeX guide, if you want to explore this further.

5
  • Are you sure that an image inclusion will be EXATCLY vertically centered using your method above? Dec 19, 2010 at 22:42
  • 1
    @xport: It might be relative to the first and last baselines of the cells, not the exact totalheight. Jul 10, 2011 at 15:53
  • 23
    When using this method, people should be cautious NOT to mix other column types such as p. The height of a row AND vertical-alignment follows that of the cell with the maximum height in that row. It is fine if an m column cell has the maximum height, but otherwise the vertical-align would not work.
    – Achimnol
    Dec 27, 2012 at 15:22
  • If you just want equally spaced columns and the whole table's width to be \textwidth, can't do that with a general m{something}?
    – Zack Fair
    Feb 25, 2017 at 4:59
  • 2
    @jimioke How does one align vertically with defining a space ie can it be written as m{}
    – 3kstc
    Apr 30, 2018 at 4:13
29

I will replicate @xport's answer with my new LaTeX3 package tabularray. It is much easier while the images are still exactly vertically centered using this method.

Specifically, the values m or h are passed to the valign= key which centers the content, which can be found in section 2.5 Rows and Columns in the documentation.

\documentclass{article}

\usepackage[a4paper,vmargin=2cm,hmargin=1cm]{geometry}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{tabularray}

\setlength{\parindent}{0pt}

\newcommand{\dummy}{%
  It is practically a big lie that \LaTeX\ 
  makes you focus on the content without
  bothering about the layout.%
}

\newcommand\xx{$\displaystyle\frac{a+b}{a-b}=0$}
\newcommand\yy{$\displaystyle\int_a^bf(x)\,\textrm{d}x=\frac{a-b}{a+b}$}
\newcommand\zz{\fcolorbox{cyan3}{yellow9}{\parbox{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}{\dummy}}}

\begin{document}

\noindent
\begin{tblr}{
  colspec = {X[c,h]X[c]X[c]X[c]},
  stretch = 0,
  rowsep = 6pt,
  hlines = {red5, 1pt},
  vlines = {red5, 1pt},
}
  \includegraphics[width=0.22\textwidth]{example-image-a} & \xx & \yy & \zz \\
  \includegraphics[width=0.22\textwidth]{example-image-b} & \xx & \yy & \zz \\
\end{tblr}

\bigskip

\begin{tblr}{
  colspec = {X[c,m]X[c,m]X[c,m]X[c,m]},
  cell{1}{3} = {c=2}{c}, % multicolumn
  cell{2}{1} = {c=2}{c}, % multicolumn
  cell{3}{2} = {c=2}{c}, % multicolumn
  cell{4}{1} = {c=4}{c}, % multicolumn
  rowsep = 6pt,
  hlines = {red5, 1pt},
  vlines = {red5, 1pt}, % vlines can not pass through multicolumn cells
}
  \yy & \yy & \yy &     \\
  \yy &     & \yy & \yy \\
  \yy & \yy &     & \yy \\
  \yy &     &     &     \\
\end{tblr}

\end{document}

enter image description here

2
  • I add the pointer to the relevant documentation section, I hope you don't mind. (it's hard to search for single-character keys) -- also, I think if you say (in the manual) t and b vertical alignment are counterintuitive, it would makes more sense to default to h type instead. (may break some backwards compatibility however.)
    – user202729
    Feb 3 at 15:22
  • Side note, the reason why in the first table it need to be of type h instead of the usual m has something to do with baseline, and is explained in Vertical alignment broken with graphics in tabularray - TeX - LaTeX Stack Exchange.
    – user202729
    Feb 3 at 16:36
27

Putting a tabular in the cell of a tabular centers the content of the cell horizontally and vertically.

\begin{tabular}{|l|c|c|}
\hline
  \begin{tabular}{l}
    text in cell 1
  \end{tabular} &
  \begin{tabular}{l}
    first line of text in cell 2 \\
    second line of text in cell 2
  \end{tabular} &
  \begin{tabular}{l}
    first line of text in cell 3 \\
    second line of text in cell 3 \\
    third line of text in cell 3 \\
  \end{tabular}
  \\
  \hline
  \begin{tabular}{l}
    first line of text in cell 4 \\
    second line of text in cell 4
  \end{tabular} &
  \begin{tabular}{l}
    first line of text in cell 5 \\
    second line of text in cell 5 \\
    third line of text in cell 5 \\
  \end{tabular} &
  \begin{tabular}{l}
    first line of text in cell 6 \\
    second line of text in cell 6 \\
  \end{tabular} \\
\hline
\end{tabular}

gives:

enter image description here

so you can define a macro centered

\newcommand{\centered}[1]{\begin{tabular}{l} #1 \end{tabular}}

and use it like this:

%\begin{tabular}{|l|c|c|}  <- Old version of this answer
\begin{tabular}{|@{}l@{}|@{}c@{}|@{}c@{}|}
% This update now avoids double indentations and allows hlines
\hline
  \centered{ text in cell 1 } &
  \centered{
    first line of text in cell 2 \\
    second line of text in cell 2} &
  \centered{
    first line of text in cell 3 \\
    second line of text in cell 3 \\
    third line of text in cell 3 \\ } \\
  \hline
  \centered{
    first line of text in cell 4 \\
    second line of text in cell 4 } &
  \centered{
    first line of text in cell 5 \\
    second line of text in cell 5 \\
    third line of text in cell 5 \\ } &
  \centered{
    first line of text in cell 6 \\
    second line of text in cell 6 \\ } \\
\hline
\end{tabular}
7
  • 2
    This doesn't seem to work in a tabularx env.
    – oarfish
    May 24, 2019 at 7:07
  • 3
    It looks like you produce double inner indentation in each cell. So it makes sense to define command this way \newcommand{\centered}[1]{\begin{tabular}{@{}l@{}} #1 \end{tabular}}
    – Smylic
    Jan 26, 2020 at 16:13
  • This works great except for when I try to add a horizontal line in a child tabular. The line does not stretch the full width of the parent cell. How would I go about changing this? Mar 19, 2020 at 4:47
  • 1
    @SanzioAngeli : Use \begin{tabular}{|@{}l@{}|@{}c@{}|@{}c@{}|} instead of \begin{tabular}{|l|c|c|}. I edited the answer accordingly. Mar 19, 2020 at 8:41
  • 5
    didn't work for me :-/
    – Daniel
    Apr 22, 2020 at 20:07
11

There is a command \vcenter which vertically centers its content in horizontal mode. It can only be used in mathmode.

Here is an example with Plain XeTeX (compile with xetex yourfilename.tex)

{ \offinterlineskip
  \def\trule{\noalign{\hrule}}
  \def\hcenter#1{\hfil#1\hfil}
  \halign{\vrule#&&\hcenter{$\vcenter{\hbox{#}}$}\vrule\cr\trule
    &Lorem ipsum dolor sit amet&\XeTeXpicfile "test-pattern.jpg" &
      \TeX&$E=mc^2$&$\displaystyle{a^2-b^2\over c^2}$\cr\trule
    &Etiam quam lacus&\vrule width 4em height 5ex depth 2ex&\eTeX &
      $E\ne mc^2$&{\it \&} cetera\cr\trule}
}
\bye

enter image description here

11

I just found this solution for a spacing Problem. When the spaceing is set at a big enough distance, the text is centered, or at least seems like.

\Huge Text in Tabular touches table border

Here is my example:

\usepackage{makecell}%To keep spacing of text in tables
\setcellgapes{4pt}%parameter for the spacing


\begin{table}[h]
    \makegapedcells
    \centering
    \resizebox{\textwidth}{!}{%resizing the whole table
\begin{tabular}{|c|c|c|c|c|c|c|c|c|}
    \hline 
    \multicolumn{9}{|c|}{\Huge Relaisplatine} \\ 
    \hline 
    Relay Nr. & Part & Test-Id & \specialcell[c]{Signal-Name \\for Testcases} & Conn. & Pin & \specialcell[c]{Pin-\\Func.} & R Value & \specialcell[c]{Influenced \\ Signal/Voltage } \\ 
    \hline 
     &  &  &  &  & 1 & N.C. & Open & Open \\
    \cline{6-9} 
    %\hline 
    0 & RIO & RIO\_VOLT\_SDAR & RIO\_GPP\_VCORE & P2 & 3 & COM &  0 $\Omega$ & SIGN08116 \\
    \cline{6-9}  
    %\hline 
    &  &  &  &  & 5 & N.O. &  0 $\Omega$ & GND \\
    %\cline{6-9}  
    \hline 
    &  &  &  &  & 7 & N.C. &  Open & Open \\ 
    \cline{6-9} 
    1 & RIO & RIO\_VOLT\_SDAR & RIO\_ETH\_+1V2 & P2 & 9 & COM &  0 $\Omega$ & SIGN0818 \\ 
    \cline{6-9}
    &  &  &  &  & 11 & N.O. &  0 $\Omega$ & GND \\ 
    \hline 
    &  &  &  &  & 13 & N.C. &  Open & Open \\ 
    \cline{6-9} 
    2 & RIO & RIO\_VOLT\_SDAR & RIO\_CLOCK\_+3V3 & P2 & 15 & COM &  0 $\Omega$ & SIGN0817 \\ 
    \cline{6-9} 
    &  &  &  &  & 17 & N.O. &  0 $\Omega$ & GND \\ 
    \hline 
    &  &  &  &  &  & N.C. &  Open & Open \\ 
    \cline{6-9} 
    3 & RIO & RIO\_VOLT\_SDAR & RIO\_HICURR1 & P3 & PCB-Cable & COM &  0 $\Omega$ & RIO\_+3V3 \\ 
    \cline{6-9} 
    &  &  &  &  & PCB-Cable & N.O. &  0 $\Omega$ & GND \\ 
    \hline 
    &  &  &  &  &  & N.C. &  Open & Open \\ 
    \cline{6-9} 
    4 & RIO & RIO\_VOLT\_SDAR & RIO\_HICURR2 & P3 & PCB-Cable & COM &  0 $\Omega$ & RIO\_+3V3 \\ 
    \cline{6-9} 
    &  &  &  &  & PCB-Cable & N.O. &  0 $\Omega$ & GND \\ 
    \hline 
    &  &  &  &  & 14 & N.C. &  Open & Open \\ 
    \cline{6-9} 
    5 & RIO & RIO\_VOLT\_SDAR & BAT\_LOW TBD & P2 & 16 & COM &  0 $\Omega$ & TBD \\ 
    \cline{6-9} 
    &  &  &  &  & 18 & N.O. &  0 $\Omega$ &  \\ 
    \hline 
    &  &  &  &  & 8 & N.C. &  Open & Open \\ 
    \cline{6-9} 
    6 & RIO & RIO\_VOLT\_SDAR & BAT\_EMPTY TBD & P2 & 10 & COM &  0 $\Omega$ & TBD \\ 
    \cline{6-9} 
    &  &  &  &  & 12 & N.O. &  0 $\Omega$ &  \\ 
    \hline 
    &  &  &  &  & 2 & N.C. &  Open & Open \\ 
    \cline{6-9} 
    7 & RIO & RIO\_VOLT\_SDAR & RIO\_DSP\_+3V3 & P2 & 4 & COM &  0 $\Omega$ & SIGN08150 \\ 
    \cline{6-9} 
    &  &  &  &  & 6 & N.O. &  0 $\Omega$ & Open \\ 
    \hline 
\end{tabular}
    }
\caption{Verkabelung der ersten Relaisplatine an X400/PortA}
\end{table}

Gives me: enter image description here

9

If you just want to center the text because you are not happy with the default row height, you can put the following command before each tabular environment:

\renewcommand{\arraystretch}{number}

where number is the factor to multiply the default row height.

1

I found out a different approach that doesn't require extra packages or redefining stuff (I guess it only works properly with one line of text in each cell).

For padding at the top you can use this solution (I found it here):

\rule{0pt}{4ex}

...which creates vertical space to by adding an invisible (0 width) horizontal bar of the height you need (in this case, 4 times the lowercase x, counting from the text baseline). This one goes before the first cell content.

For padding at the bottom, you just add the needed space after the line ends:

cell & cell & cell \\[4ex]

Note: For a nice balance I found that the top padding needs to be 2.2ex more than the bottom one (to compensate for the height of the text itself).

\rule{0pt}{4.2ex} cell & cell & cell \\[3ex]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .