71

Consider the following hunk of code:

\begin{tabular}{| c | c | c | c | c | c | c | }
\cline{2-7}
\multicolumn{1}{c}{} & \multicolumn{3}{|c|}{Fantastical aardvarks}  
& \multicolumn{3}{c|}{Spelunking elephants}\\
\hline
 Foo bar & A & B & C & A & B & C\\
\hline
 5 & 87 &  5 &  2 & 82 & 18 & 48\\
 6  & 5 & 43 &  4 & 7 & 47 & 4\\
 7 &  7 &  18 & 63 & 2 & 9 & 99\\
\hline
\end{tabular}

misaligned tables

Is there a way to have the three columns under "Fantastical aardvarks" and, separately, under "Spelunking elephants" have widths that are evenly distributed?

I'm particularly interested in an automated way of doing this, without needing to directly specify column widths.

4 Answers4

72

You could use the tabularx environment instead of the tabular environment. The tabularx environment, made available by loading the tabularx package, provides a column type called "X" that should satisfy your professed need to have several equal-width columns. The first table in the MWE below explains how to do this.

There is one decision, however, that the author must make, i.e., which can't be automated entirely: How wide should the entire table be? Often, one simply sets this width to \textwidth (the width of the current textblock) and then lets tabularx determine how wide the individual columns of type X will be. For this MWE (which uses the default text font employed by LaTeX), with some trial-and-error work I found that it's possible to specify the table's overall width as narrow as about 0.75\textwidth. For your actual document, you will need to play around with the table width settings to determine empirically what the narrowest possible table width may be.

Note also the use of the specifier \centering\arraybackslash before the X column type in the MWE. I've inserted this specifier as it appears that you want the contents of the columns to be centered. (The contents of an X column are set "fully justified" by default.)

That said, I'd also like to very strongly encourage you to consider (i) getting rid of all vertical lines in the table and (ii) using the booktabs package to getter spacing above and below the various rules in the table. This package provides the commands \toprule, \bottomrule, \midrule, and \cmidrule; how to use them is explained in the second part of the MWE below. Note that it's possible to left-trim and/or right-trim a \cmidrule -- something that's quite impossible to achieve with \cline. Comparing the two forms of the table, I daresay predict that the overwhelming majority of readers will find the second form to be both more pleasing to look at and more easily understandable. :-)

enter image description here

\documentclass{article}
\usepackage{tabularx,booktabs}
\newcolumntype{Y}{>{\centering\arraybackslash}X}

\begin{document}

\noindent
\begin{minipage}{0.75\linewidth}

First version: Many vertical lines, 
widths of horizontal lines all equal, 
spacing above\slash below horizontal 
lines cramped

\smallskip
\begin{tabularx}{\textwidth}{ |c| *{6}{Y|} }
\cline{2-7}
   \multicolumn{1}{c|}{} 
 & \multicolumn{3}{c|}{Fantastical aardvarks}  
 & \multicolumn{3}{c|}{Spelunking elephants}\\
\hline
 Foo bar & A & B & C & A & B & C\\
\hline
 5  & 87 &  5 &  2 & 82 & 18 & 48\\
 6  &  5 & 43 &  4 &  7 & 47 &  4\\
 7  &  7 & 18 & 63 &  2 &  9 & 99\\
\hline
\end{tabularx}

\bigskip

Second version: No vertical lines, 
widths of horizontal lines differ, 
spacing above/below horizontal lines 
satisfactory

\smallskip
\begin{tabularx}{\textwidth}{c *{6}{Y}}
\toprule
Foo bar
 & \multicolumn{3}{c}{Fantastical aardvarks}  
 & \multicolumn{3}{c}{Spelunking elephants}\\
\cmidrule(lr){2-4} \cmidrule(l){5-7}
  & A & B & C & A & B & C\\
\midrule
 5  & 87 &  5 &  2 & 82 & 18 & 48\\
 6  &  5 & 43 &  4 &  7 & 47 &  4\\
 7  &  7 & 18 & 63 &  2 &  9 & 99\\
\bottomrule
\end{tabularx}
\end{minipage}
\end{document}
Mico
  • 506,678
  • Thanks! One followup: you've specified that you need to set the width of the entire table. Is there a way to do this without that specification? Ideally, for a smaller table, I'd rather it not be that wide. Or is specifying the entire width worth the effort for the better column spacing? – Eli Lansey Jun 20 '12 at 19:52
  • To make the vertical rules line up, rather use \multicolumn{1}{c|}{} & \multicolumn{3}{c|}{Fantastical aardvarks} & \multicolumn{3}{c|}{Spelunking elephants}. @EliLansey: You can use something smaller than \textwidth (or \linewidth), like .5\linewidth for a 50% width table. – Werner Jun 20 '12 at 19:54
  • I suppose the X column widths will have to be at least 1/3 of the max of the string lengths of "Fantastical aardvarks" and "Spelunking elephants". (However, in your actual table you will have different entries, right?!) The minimum table width will also depend on factors such as the font and font size in use. Unless you have lots and lots of tables of this sort, you're probably best off going the trial-and-error route, i.e., try out 0.8\textwdith, 0.75\textwidth, etc until the table doesn't look right. – Mico Jun 20 '12 at 19:59
  • @Werner -- thanks, I'll correct the code to incorporate your suggestions! – Mico Jun 20 '12 at 20:00
  • @Werner I'm not sure I understand your first sentence. – Eli Lansey Jun 20 '12 at 20:00
  • @Mico OK, fair enough. – Eli Lansey Jun 20 '12 at 20:00
  • @EliLansey: The two heading columns' vertical lines don't line up around Fantastical aardvarks. My suggestion just shifted the positioning of the vertical rules. A variation using booktabs is a clean alternative, since the table layout already imposes some horizontal organization of data, and therefore doesn't require more vertical rules. Read the booktabs documentation for more on table design and layouts. – Werner Jun 20 '12 at 20:11
  • @Mico Thanks. Can you include the booktabs example Gonzalo had up, too? – Eli Lansey Jun 20 '12 at 20:19
  • @GonzaloMedina Can you edit this answer to include your booktabs addition? – Eli Lansey Jun 20 '12 at 20:25
  • @Mico What is the difference between \cmidrule(lr) and \cmidrule(l) in the second example? – Eli Lansey Jun 20 '12 at 20:36
  • @EliLansey: The (lr) option trims the rule on both the left and right, while the (l) option trims the rule only on the left-hand side. – Mico Jun 20 '12 at 20:38
  • How do I modify this solution to include also the first column to be equally spaced? – Filippo Bistaffa Jul 30 '18 at 11:09
  • @FilippoBistaffa - Please clarify what you mean by "equally spaced"? E.g., do you mean, "as wide as the other 6 columns"? Please advise. – Mico Jul 30 '18 at 11:13
  • Yes, I would like to have all 7 columns equally wide (in this example). – Filippo Bistaffa Jul 30 '18 at 11:33
  • @FilippoBistaffa - And are you interested in the first solution (the one with lots of vertical bars) or in the second? – Mico Jul 30 '18 at 11:36
  • The second one. – Filippo Bistaffa Jul 30 '18 at 11:39
  • @FilippoBistaffa - In that case, you should try replacing (a) \begin{tabularx}{\textwidth}{ |c| *{6}{Y|} } with \begin{tabularx}{\textwidth}{ |*{7}{Y|} } and (b) Foo bar with \smash{\begin{tabular}[t]{@{}c@{}}Foo\bar\end{tabular}}. – Mico Jul 30 '18 at 11:42
  • @Mico How to modify this for a longtable? – Subhajit Paul Mar 13 '20 at 16:54
  • @SubhajitPaul - Please search this site for queries about how to fuse the capabilities of longtable and tongtable. (The packages can't be used together.) Or, post a new query. – Mico Mar 13 '20 at 18:06
13
\documentclass{article}
\usepackage{tabularx,ragged2e}
\usepackage{booktabs}

\begin{document}

{\tabcolsep=0pt\def\arraystretch{1.3}
\begin{tabularx}{250pt}{c *6{>{\Centering}X}}\toprule
  & \multicolumn{3}{c}{Fantastical aardvarks}   & \multicolumn{3}{c}{Spelunking elephants} 
  \tabularnewline \cmidrule(lr){2-4}\cmidrule(l){5-7}
  Foo bar & A & B & C & A & B &  C \tabularnewline \midrule
  5  & 87 &  5 &  2 & 82 & 18 & 48 \tabularnewline
  6  &  5 & 43 &  4 &  7 & 47 & 4 \tabularnewline
  7  &  7 & 18 & 63 &  2 &  9 & 99 \tabularnewline\bottomrule
\end{tabularx}}

\end{document}

enter image description here

4

Late to the party, but I had the same problem with a table that was so large, that tabularx would blow the table out of the page boundaries no matter what I did. So I could not use tabularx, instead I found a cheap dirty trick: \hspace*{}

Just place \hspace*{} in the column that you want to enlarge. Since you want centered columns, you have to place it before and after the text of the top row:

\begin{tabular}{| c | c | c | c | c | c | c | }
\cline{2-7}
\multicolumn{1}{c}{} & \multicolumn{3}{|c|}{Fantastical aardvarks}  
& \multicolumn{3}{c|}{Spelunking elephants}\\
\hline
Foo bar &\hspace*{1.5mm} A \hspace*{1.5mm} & \hspace*{1.5mm} B \hspace*{1.5mm} & C & A & B & C\\
\hline
 5 & 87 &  5 &  2 & 82 & 18 & 48\\
 6  & 5 & 43 &  4 & 7 & 47 & 4\\
 7 &  7 &  18 & 63 & 2 & 9 & 99\\
\hline
\end{tabular}

compiled example

You need to play around a bit to get the right precision, but sometimes you just have to play dirty.

And
  • 269
  • 2
    If one is to approach this in the way you have (manually spacing), I'd suggest using >{\hspace*{1.5mm}} in the column declaration rather than in the tabular content itself. – likethevegetable Jul 18 '21 at 15:21
4

It’s easy peasy with tblr environment of the new LaTeX3 package tabularray:

\documentclass{article}
\usepackage{tabularray}
\begin{document}

\begin{tblr}{ hline{1} = {2-7}{solid}, hline{2,3,6} = {solid}, vline{1} = {2-5}{solid}, vline{2-Z} = {solid}, % Z stands for the last cells = {c}, cell{1}{2,5} = {c=3}{c}, % multicolumn hspan = even, % evenly distributing column widths } & Fantastical aardvarks & & & Spelunking elephants & & \ Foo bar & A & B & C & A & B & C \ 5 & 87 & 5 & 2 & 82 & 18 & 48 \ 6 & 5 & 43 & 4 & 7 & 47 & 4 \ 7 & 7 & 18 & 63 & 2 & 9 & 99 \ \end{tblr}

\end{document}

enter image description here

L.J.R.
  • 10,932