# Change Content Font in tabular Environments

I am trying to change the font in the content of all of the tables in a document from a serif font to a sans-serif font.

Specifically, I need something that can be applied to tabular and tabular* environments, so that the captions are not changed. For the sake of avoiding dependencies, I am looking for a solution that can be implemented without other packages and eventually added to a style file.

My current solution is to modify the table environment like this:

\makeatletter
\renewenvironment{table}
{\@float{table} \fontfamily{phv}\selectfont}
{\end@float}
\makeatother


In a MWE, this looks like this:

\documentclass[preview]{standalone}

\usepackage{setspace}
\usepackage{booktabs}

\makeatletter
\renewenvironment{table}
{\@float{table} \fontfamily{phv}\selectfont}
{\end@float}
\makeatother

\RequirePackage[format=plain,
labelformat=simple,
font={small,sf,bf},
indention=0cm,
labelsep=period,
justification=centering,
singlelinecheck=true,
tableposition=top,
figureposition=bottom]{caption}

\begin{document}

Blah blah. Should be a serif font.

\begin{table}[h]
\caption{Some caption, which should be bold.}
\label{tab:xxx}\centering
\begin{tabular}{ccc}
test1 & test2 & test3 \\
\toprule
test1 & test2 & test3 \\
test1 & test2 & test3 \\
test1 & test2 & test3 \\
\bottomrule
\end{tabular}
\end{table}

Blah blah. Should be a serif font.

\end{document}


It all works, except modifying the environment definition results in a little [h] swimming around.

What am I doing wrong?

• I wrote an introduction to this syntax in this answer which may (or may not) be helpful. – cfr Jan 9 '16 at 0:16
• Question updated to make it clear that I effectively want to change the tabular and tabular* environments – Andy Clifton Jan 11 '16 at 2:03

## The Problem

The reason you get the floating [h] is that your redefinition does not accept an argument. Normally, you'd specify an option argument using something like

\renewenvironment{table}[1][]


Now, in fact, this is not how the standard classes handle the optional argument in this case. article.cls defines the environment with no optional argument at all:

\newenvironment{table}
{\@float{table}}
{\end@float}


So why does it work? It works because of the way \@float is defined in latex.ltx:

\def\@float#1{%
\@ifnextchar[%
{\@xfloat{#1}}%
{\edef\reserved@a{\noexpand\@xfloat{#1}[\csname fps@#1\endcsname]}%
\reserved@a}}


\@float takes the {table} as the first, required, argument, and then scans ahead to see if the next token is a [ and, if so, it processes the contents of the [...] as an argument specifying the placement options for the float. This relies on the [ being the next thing in the input stream. If you change the definition to do something else first:

\renewenvironment{table}
{\@float{table} \fontfamily{phv}\selectfont}
{\end@float}


then the next token is not [, so LaTeX assumes there is no optional argument in this case and processes the rest as the contents of the environment.

If you want the optional argument just disposed of, you can throw it away

\renewenvironment{table}[1][]


However, if you want the optional argument to be processed as usual, then it must be passed to \@float{table} so it must come before the font specification.

## A Solution

You could redefine the environment to handle the argument. However, I would recommend patching the environment rather than overwriting it. This requires etoolbox but the package is very widely used and many documents will load it anyway. I would also recommend not hard-coding the font family but using the document's default sans-serif family.

Here's one way to do it, though I'm not sure that this is the best approach.

\makeatletter
\newcommand*\my@starttable[1][]{%
\@float{table}[#1]\sffamily
}
\patchcmd{\table}{\@float{table}}{\my@starttable}{\PackageInfo{mysty}{Table environment patched successfully.}}{\PackageWarning{mysty}{Could not patch table environment.}}
\makeatother


mysty should be replaced with the name of your package, of course, when this goes into the .sty file.

Complete code:

\documentclass{article}
\usepackage{setspace}
\usepackage{booktabs}
\usepackage{etoolbox}
\usepackage[format=plain,
labelformat=simple,
font={small,sf,bf},
indention=0cm,
labelsep=period,
justification=centering,
singlelinecheck=true,
tableposition=top,
figureposition=bottom]{caption}
\makeatletter
\newcommand*\my@starttable[1][]{%
\@float{table}[#1]\sffamily
}
\patchcmd{\table}{\@float{table}}{\my@starttable}{\PackageInfo{mysty}{Table environment patched successfully.}}{\PackageWarning{mysty}{Could not patch table environment.}}
\makeatother
\begin{document}

Blah blah. Should be a serif font.

\begin{table}[h]
\caption{Some caption, which should be bold.}
\label{tab:xxx}\centering
\begin{tabular}{ccc}
test1 & test2 & test3 \\
\toprule
test1 & test2 & test3 \\
test1 & test2 & test3 \\
test1 & test2 & test3 \\
\bottomrule
\end{tabular}
\end{table}

Blah blah. Should be a serif font.

\end{document}

• Instead of patching the low level commands why not just use \AtBeginEnvironment{table}{\sffamily}{}{}? – Alan Munn Jan 9 '16 at 4:48
• @AlanMunn No, it doesnt' work. – egreg Jan 9 '16 at 11:20
• @AlanMunn What egreg said. Actually, I didn't try that specifically. But I did try something similar which fails for the same reason. – cfr Jan 9 '16 at 20:27
• Well, cfr wins the prize for answering the question, but egreg's solution is cleaner. – Andy Clifton Jan 11 '16 at 1:59
• @AndyClifton Initially, I planned to only answer the question. Probably should have stuck to that ;). – cfr Jan 11 '16 at 2:03

It's much easier using the “reset” hook provided by the kernel:

\documentclass{article}

\usepackage{booktabs}
\usepackage{etoolbox}
\usepackage[format=plain,
labelformat=simple,
font={small,sf,bf},
indention=0cm,
labelsep=period,
justification=centering,
singlelinecheck=true,
tableposition=top,
figureposition=bottom]{caption}

\makeatletter
\appto\@floatboxreset{%
\ifx\@captype\andy@table
\sffamily
\fi
}
\def\andy@table{table}
\makeatother

\begin{document}

Blah blah. Should be a serif font.

\begin{table}[htp]
\caption{Some caption, which should be bold.}
\label{tab:xxx}\centering
\begin{tabular}{ccc}
test1 & test2 & test3 \\
\toprule
test1 & test2 & test3 \\
test1 & test2 & test3 \\
test1 & test2 & test3 \\
\bottomrule
\end{tabular}
\end{table}

Blah blah. Should be a serif font.

\end{document}


Before any text in the float is typeset, LaTeX calls \@xfloatreset, which normally does \reset@font\normalsize\@setminipage, but anything desired can be added. In this case we compare \@captype (which essentially holds the name of the called float) with a fixed string. Thus, if the float is a table, \sffamily is called.

The seemingly easier

\AtBeginEnvironment{table}{\sffamily}


wouldn't work, exactly because \@xfloatreset issues \normalfont.

• @AndyClifton etoolbox is definitely required. It defines \apptocmd. I agree this solution is cleaner. As I said, I should have stuck to just answering the question. – cfr Jan 11 '16 at 2:05
• This works nicely and redefines both the tabular and tabularx environments, which is a plus. Also, it looks like the etoolbox package isn't required for this to work (despite it being in the preamble that egreg provides). It's the solution I used, but not the answer to the question. Can I give you a bounty? – Andy Clifton Jan 11 '16 at 2:05
• @AndyClifton I'm not trying to steal the tick back. I think it is cleaner. I would not think its use of etoolbox is a mark against it even if my solution didn't use that as well. – cfr Jan 11 '16 at 2:07

If you have only the tabular environment in your table environment then you can redefine \tabular:

\documentclass{article}

\usepackage{booktabs}
\usepackage[format=plain,
labelformat=simple,
font={small,sf,bf},
indention=0cm,
labelsep=period,
justification=centering,
singlelinecheck=true,
tableposition=top,
figureposition=bottom]{caption}

\let\Tabular\tabular
\def\tabular{\sffamily\Tabular}

\begin{document}

Blah blah. Should be a serif font.

\begin{table}[htp]
\caption{Some caption, which should be bold.}
\label{tab:xxx}\centering
\begin{tabular}{ccc}
test1 & test2 & test3 \\
\toprule
test1 & test2 & test3 \\
test1 & test2 & test3 \\
test1 & test2 & test3 \\
\bottomrule
\end{tabular}
\end{table}

Blah blah. Should be a serif font.

\end{document}


• This is the simplest solution as far as I can tell, but it doesn't work on the tabular* environment. – Andy Clifton Jan 11 '16 at 1:52
• @AndyClifton And it is not a solution to the problem posed in the question. As well as tabular*, if your table environments sometimes contain other things e.g. tabularx or threeparttable or whatever, then you would have to redefine those as well, I think. (Unless those internally use \tabular.) If the question asked about changing the content font for tabular, it would be a different question ;). Which isn't to say this isn't a better solution if that is really what you need. – cfr Jan 11 '16 at 1:56

Instead of running

\fontfamily{phv}\selectfont


after \@float{table} in the redefinition of the table environment, I recommend you execute

\renewcommand\familydefault\sfdefault\selectfont


before \@float{table}. That way, the code doesn't mess with the operation of \@float (and its handling of placement options such as h).

Separately, I suggest you execute the instruction

\usepackage[scaled=0.83]{helvet}


in the preamble to make Helvetica the default sans-serif font, while scaling the font so that its x-height matches that of the document's serif font.

With these changes, your code executes as expected, i.e., the h placement option is processed correctly.

Note that the solution automatically applies to all tabular-like environments that may be used in table environments -- tabular, tabular*, tabularx, tabulary, etc.

\documentclass{article}

\usepackage{setspace,booktabs}

% Use Helvetica as the sans-serif font, and equalize the x-heights of
% the document's serif and sans-serif fonts.
\usepackage[scaled=0.83]{helvet}

\makeatletter
\renewenvironment{table}
{\renewcommand\familydefault\sfdefault\selectfont
\@float{table}}
{\end@float}
\makeatother

\RequirePackage[format=plain,
labelformat=simple,
font={small,bf}, % no need to specify 'sf' option
indention=0cm,
labelsep=period,
justification=centering,
singlelinecheck=true,
tableposition=top,
figureposition=bottom]{caption}

\begin{document}
Blah blah. Should be a serif font.

\begin{table}[h]
\caption{Some caption, which should be bold}
\label{tab:xxx}
\centering
\begin{tabular}{ccc}
\toprule
test1 & test2 & test3 \\
\midrule
test1 & test2 & test3 \\
test1 & test2 & test3 \\
test1 & test2 & test3 \\
\bottomrule
\end{tabular}
\end{table}

Blah blah. Should be a serif font.
\end{document}

• Also seems to work nicely. I like the rescaling of the font. – Andy Clifton Jan 11 '16 at 3:21
• This worries me. Who expects a table to change the default font family? That is, it seems anti-semantic.... Good point about the scaling, though. – cfr Jan 11 '16 at 3:27
• @cfr - I once worked for an institution which required Times Roman to be used as the text font for working papers, except in figures and tables, where the text font had to be Helvetica. (I know, it was UGLY. Unfortunately, this requirement came from the Corporate Design office, and there was absolutely no arguing with them about any style-related matters.) For those of us who used LaTeX instead of MS Word, I designed a style file which (among other things) used the code shown above to implement this style requirement. The OP's requirement seems to be very much in the same spirit... – Mico Jan 11 '16 at 3:33
• @mico, yup, it's a corporate template thing. – Andy Clifton Jan 11 '16 at 12:24