8

In an attempt to separate the formatting of tables, and in particular their headers, from the content, I have produced the following code:

\documentclass{article}
\usepackage{array}
\usepackage{colortbl}
\usepackage{xcolor}


\newcolumntype{L}{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}}}
\newcolumntype{C}{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}}

\newcommand{\vheader}[1]{\multicolumn{1}{>{\bfseries}c}{#1}}
\newcommand{\fheader}[2]{\multicolumn{1}{>{\bfseries}Cb{#1}}{#2}}

\begin{document}

\begin{tabular}{cLp{50mm}lr}
  \rowcolor{black!20}
  \vheader{Rank} & 
  \fheader{50mm}{Venerable Institution of Higher Education} &
  \vheader{Location} &
  \vheader{Score} \\

  1 & California Institute of Technology (Caltech) & United States & 94.9 \\
  \multicolumn{4}{c}{\ldots}\\
  12 & University of California, Los Angeles (UCLA) & United States & 86.3 \\
  13 & Columbia University & United States & 85.2 \\
  14 & ETH Z\"urich -- Swiss Federal Institute of Technology Z\"urich & Switzerland & 84.5 \\
\end{tabular}

\end{document}

(data taken from Times Higher Education, universities chosen to have some with long names)

The idea is that table headers should be

  • bold face
  • centered
  • bottom aligned

but that these choices should be easy to change globally. Therefore I have marked up the header cells using macros \vheader for variable-width columns, like c, l, r, and \fheader for fixed-width columns like p, m, b. It works:

enter image description here

But there are three things I don't like:

  • The need to repeat the width of the column for fixed-width columns. I have found that \hsize will be set to the column width. But all my attempts to retrieve it and use it in the multicolumn preamble failed, nagging about misplaced \omit and the likes.
  • The need to say explicitly whether this is a fixed or variable width column. Again, I tried code that checks whether \hsize was changed from its value outside the tabular, and uses different multicolumn preambles depending on that, but it disagreed with multicolumn processing.
  • The need to say this for every cell, instead of once for the whole row. The tabu package has a \rowfont macro for instance, that can take care of the bold face and centering at least, though not the bottom alignment. But tabu is not maintained, and looking at the source code, this is a really brittle business that involves code in the preamble to remove the previous glue of columns, which is different depending on whether or not colortbl is used.

Suggestions for each and any of these would be welcome—sorry for asking three questions at once!

Edit: replaced booktabs by colortbl and a grey background for the header row. Coloured backgrounds are frequently asked for by designers, so it's important that this works. And colortbl can be difficult, with the background not filling the whole cell.

1
  • \newcommand\fheader[1]{\centering\arraybackslash\bfseries #1} ? Ah it doesn't work, sorry
    – yo'
    Apr 24, 2014 at 9:22

2 Answers 2

6
\documentclass{article}
\usepackage{array}
\usepackage{colortbl}
\usepackage{xcolor}


\newcolumntype{L}{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}}}
\newcolumntype{C}{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}}



\newcommand{\header}[1]{%
  \multicolumn{1}{c}{%
    \cellcolor{black!20}\bfseries\begin{tabular}[b]{@{}c@{}}#1\end{tabular}}}


\begin{document}

\begin{tabular}{cLp{50mm}lr}
  \header{Rank} & 
  \header{Venerable Institution of\\ Higher Eductation} &
  \header{Location} &
  \header{Score} \\

  1 & California Institute of Technology (Caltech) & United States & 94.9 \\
  \multicolumn{4}{c}{\ldots}\\
  12 & University of California, Los Angeles (UCLA) & United States & 86.3 \\
  13 & Columbia University & United States & 85.2 \\
  14 & ETH Z\"urich -- Swiss Federal Institute of Technology Z\"urich & Switzerland & 84.5 \\
\end{tabular}

\end{document}

Or if you don't want to specify a width or have manual linebreaking, you can use varwidth

\documentclass{article}
\usepackage{array}
\usepackage{colortbl}
\usepackage{xcolor}
\usepackage{varwidth}


\newcolumntype{L}{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}}}
\newcolumntype{C}{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}}

\newcommand{\header}[1]{%
\cellcolor{black!20}\bfseries\begin{varwidth}[b]{\hsize}\centering\let\newline\\\arraybackslash#1\end{varwidth}}


\begin{document}

\begin{tabular}{cLp{50mm}lr}
  \header{Rank} & 
  \header{Venerable Institution of Higher Eductation} &
  \header{Location} &
  \header{Score} \\

  1 & California Institute of Technology (Caltech) & United States & 94.9 \\
  \multicolumn{4}{c}{\ldots}\\
  12 & University of California, Los Angeles (UCLA) & United States & 86.3 \\
  13 & Columbia University & United States & 85.2 \\
  14 & ETH Z\"urich -- Swiss Federal Institute of Technology Z\"urich & Switzerland & 84.5 \\
\end{tabular}

\end{document}
8
  • This one avoids the problem in the title by requiring me to manually break my column titles, also in fixed width columns. The embedded tabular makes it easy to do so. Moreover, it is possible to change the alignment to top, middle, bottom, left, right. So it certainly is flexible, and it does the job no matter what the original cell format was. I like it because arguably, it's best to use manual line breaking for long column titles anyway. What I don't like is that this is less true if I want to change formatting for something else than headers! In other words, it's not very generic.
    – mabartibin
    Apr 24, 2014 at 13:40
  • @mabartibin well as you say it's a tradeoff, in TeX you always need to either specify a width or linebreak manually (well that's not true if you look at varwidth package but it's true really, varwidth just hides it:-) so you have a choice of manual breaking (and I get the tick) or specifying the width (and egreg gets the tick) but don't do that:-) But you may want to use varwidth package for a generic solution. (I'd manually line break headers anyway) Apr 24, 2014 at 13:59
  • Well, I think before setting that tick, I'll wait just a little longer to see if someone comes up with a way that is similar to egreg's solution but that can cope with a single macro…
    – mabartibin
    Apr 24, 2014 at 14:15
  • @mabartibin varwidth example added Apr 24, 2014 at 15:25
  • Thank you! But it doesn't do quite the right thing: the headers get centred in their respective varwidth boxes, but not in their columns.
    – mabartibin
    Apr 24, 2014 at 16:59
6

Just use a \parbox[b]{\hsize}{...}:

\documentclass{article}
\usepackage{array}
\usepackage{colortbl}
\usepackage{xcolor}


\newcolumntype{L}[1]{%
  >{\raggedright\let\newline\\\arraybackslash\hspace{0pt}}%
  p{#1}%
}

\newcommand{\vheader}[1]{%
   \multicolumn{1}{>{\bfseries}c}{#1}
}
\newcommand{\fheader}[1]{%
  \parbox[b]{\hsize}{%
    \centering\arraybackslash\bfseries\strut#1\strut
  }%
}

\begin{document}

\begin{tabular}{cL{50mm}lr}
  \rowcolor{black!20}
  \vheader{Rank} &
  \fheader{Venerable Institution of Higher Eductation} &
  \vheader{Location} &
  \vheader{Score} \\

  1 & California Institute of Technology (Caltech) & United States & 94.9 \\
  \multicolumn{4}{c}{\ldots}\\
  12 & University of California, Los Angeles (UCLA) & United States & 86.3 \\
  13 & Columbia University & United States & 85.2 \\
  14 & ETH Z\"urich -- Swiss Federal Institute of Technology Z\"urich & Switzerland & 84.5 \\
\end{tabular}

\end{document}

enter image description here

6
  • Thank you! That solves the issue of passing in \hsize. And the trick is that the parbox takes up the whole width of the cell, no matter whether the column was ragged right or left or justified in the first place. But I don't think the same idea can be used for the l/c/r columns, so I still need two header macros?
    – mabartibin
    Apr 24, 2014 at 13:24
  • @mabartibin The width of a p column is predetermined; the width of l, c or r columns is not.
    – egreg
    Apr 24, 2014 at 13:28
  • sure, I know. And programming a <code>\header</code> macro that inspects <code>\hsize</code> to figure out whether to use <code>vheader</code> or <code>fheader</code> will almost certainly break the <code>\multicolumn</code> again.
    – mabartibin
    Apr 24, 2014 at 13:42
  • @mabartibin Use backquotes for surrounding code. \hsize is not set in lcr columns; it will have the same value as outside the tabular.
    – egreg
    Apr 24, 2014 at 13:46
  • Oops. I realise that \hsize is not set in lcr. That's what gives me the idea of saving \hsize outside a tabular and checking whether it was reset to figure out if we're in an lcr or pmb column.
    – mabartibin
    Apr 24, 2014 at 13:54

You must log in to answer this question.

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