# What is the difference between tabular, tabular* and tabularx environments?

There have been quite a few hit on Google, including one in Tex SE, but none of those made a complete sense to me. Please don't write something like:

tabular* adjusts the space between text of adjacent columns to get a given table width, tabularx leaves this intercolumn space fixed, instead adjusts the text width within the "X" columns for same purpose.

Can anyone provide an MWE that makes sense? Code speaks better than words.

• Did you see the posting How to force a table into page width? The two top-voted answers discuss tabularx and tabular* as table-like environments that take as their first argument the intended width of the table. – Mico Nov 27 '16 at 17:28
• – Werner Nov 27 '16 at 17:40

Check out the following MWE:

\documentclass{article}

\usepackage{tabularx}

\begin{document}

\begin{tabular}{|l|c|r|}
\hline
foo   & bar    & fubar \\
fubar & toobar & foo \\
\hline
\end{tabular}

\vspace{1cm}

\begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}|l|c|r|}
\hline
foo   & bar    & fubar \\
fubar & toobar & foo \\
\hline
\end{tabular*}

\vspace{1cm}

\begin{tabularx}{\textwidth}{|X|X|X|}
\hline
foo   & bar    & fubar \\
fubar & toobar & foo \\
\hline
\end{tabularx}

\end{document}


As you notice, with the default tabular environment, columns are as wide as they need to be in order to accommodate their content.

In the tabular* version, LaTeX will add supplementary space between the columns in order to make the table as wide as specified (i.e. \textwidth). However, the columns' widths do not change. You can see that the content of the second column is not centered relatively to the two vertical bars.

If the design objective is to produce a table with equal-width columns that contain left-justified material, best results are obtained by using tabularx. The new X column type will have LaTeX automatically calculate the width of the column in order to make the table as wide as specified. You might wonder why the contents are not centered in my example. You can define centered columns with automatic width calculation, I just wanted to give a quick example without too much overhead. The package's documentation is very good, so you can easily adapt my example to suit your needs.

• What I would have written is that tabular* environments do tend to look bad if vertical rules are used in the interior of the table; the code example you use features two such vertical rules. Once the vertical rules are eliminated -- something that should probably be done anyway :-) -- the tabular* environment starts to come into its own. Incidentally, eliminating all vertical rules -- both exterior and interior -- is almost always a good idea anyway. – Mico Nov 27 '16 at 17:34
• Seriously, you downvote an answer for one single word? I have never seen that on TeX.SE. If you are not happy with the answer, just write a better one. I use rules to show the effect (intercolumn space vs. larger columns), discussion about table formatting is OT here, don't you think? You are right that "best" is not the good word, as it depends on what one wants to achieve. I however stick to saying that if you want to force a table to some overall width, tabularx intuitively gives better results, as it is strange to have centered content not aligned in the middle of a column. – Philipp Imhof Nov 27 '16 at 20:52
• It was a whole sentence I reacted to, not just a single word. As I explained in the second comment, tabular* does have potentially serious limitations -- under certain circumstances, which I was careful to lay out. Your claim seems to assert that it's valid at a rather high level of generality; you may want to explain in more detail under which circumstances tabularx is "best". After all, there are many table layouts quite different from the one studied in your MWE. About downvoting: when I get downvoted, the downvoter rarely bothers with the courtesy of explaining what may be wrong. – Mico Nov 27 '16 at 21:04
• I've taken you up on your suggestion to write an answer of my own. I've also taken the liberty of editing your posting slightly to fix a couple of typos, add a few backticks, and put in a qualifier as to when tabularx is "best". I've also reversed my vote. :-) – Mico Nov 27 '16 at 22:55

I will begin by showing a screenshot of tabular, tabular* and tabularx versions of one and the same, admittedly contrived, table. The material in the first column is left-aligned; the material in the five data columns is centered; the precise nature of the centering method is explained below. Incidentally, there are no vertical rules in the tables. The horizontal rules are generated by the macros of the booktabs package (\toprule, \cmidrule, \midrule, and \bottomrule).

## tabular vs. tabular*

• The most significant difference between the tabular and tabular* environments is that the latter can be set to occupy a pre-specified width. Often, but not necessarily, this width will be \textwidth, i.e., the width of the textblock. (In the example above, the width of the tabular* and tabularx environments is set to 0.85\textwidth.) Achieving the target width, which is specified in the first argument of tabular*, is accomplished by inserting the admittedly not-exactly-obvious-looking [!] directive @{\extracolsep{\fill}} inside the second argument of tabular*.

• Otherwise, the tabular and tabular* environments have the same features. In particular, they "know" about the same basic column types: l, c, r, and p. Additional column types may be set up by loading dedicated packages (e.g., dcolumn and siunitx for the D and S column types) and by loading the array package and making use of that package's \newcolumntype macro.

• A consequence of the @{\extracolsep{\fill}} directive in the tabular* environment is that the column contents continue to be typeset at their natural widths; what's adjusted is the amount of inter-column whitespace. This may be verified visually by looking closely at the five data columns in the first two tables: Their column type is c in both cases. Notice that the "BB" and "DD" columns are rather wider than the "AA", "CC", and "EE" columns. Having different column widths may be either innocuous or it may be problematic. If there are lots of columns and the column widths are rather different, a visual eye-sore might occur. Achieving a common column width despite differences in column contents is one very good reason for using tabularx; see below for more on this subject.

• By the way, tabular*-based tables tend to look awful if they contain internal vertical rules. The tables shown in the screenshot don't contain either exterior or interior vertical rules. Omitting all vertical rules is usually a good idea anyway.

## Why set a target width?

• A separate issue: Why bother setting a target width? Why not just let the table occupy its natural width (assuming, of course, that it fits inside the text block)? Using the natural width, for sure, makes for the most compact-looking tables; compactness is often -- but not always... -- desirable. A design issue can arise if your document has lots of tables and if the tables all have rather different natural widths. In such cases, the document quickly takes on a ragged and uneven look. Setting all tables to occupy the same width -- say, \textwidth -- sidesteps this problem. A personal anecdote: I once was in charge of creating a conference proceedings volume -- using LaTeX, of course :-) -- and I worked with a talented in-house book designer to arrive at all layout decisions. The book eventually contained about 15 papers, and virtually all papers contained quite a few tables. The book designer quickly convinced me that the document -- in this case, an entire book -- would look a lot better if all tables shared a common width. [This all happened before the tabularx package came along; back then, tabular* was the only game in town.]

## tabularx and tabular* compared

• In order to use the tabularx environment, the tabularx package must be loaded. This package provides a new column type called X, which is a derivative of the basic-LaTeX p column type. Like the tabular* environment, the tabularx environment takes two arguments: the intended width and the set of column specifications. Significantly, it's not necessary to specify something like @{\extracolsep{\fill}} to achieve the overall target width. Instead, the package automatically calculates the widths of the X columns to achieve the overall target width. Indeed, every tabularx environment must have at least one X column if the desired overall width is to be achieved.

• By default, the X columns typeset their material in fully-justified or "paragraph" mode. This may be changed by using \newcolumntype directives; for the tabularx environment shown in Table 3 of the screenshot, a column type called C is used. Since both X and C columns are (ultimately) based on LaTeX's p column type, line breaking will be applied automatically if needed. Importantly, instead of expecting the user to perform the calculations to come up with a suitable width for each p column, LaTeX performs the required calculations itself.

• Importantly, unless one goes out of one's way to change the defaults, all X and C columns in a given tabularx environment have the same width by construction. This often (but not always) makes for a very pleasing overall look. I'd say that having equal columns widths is often a very good reason for using a tabularx environment.

• Let us now compare the looks of the tables produced by the tabular* and tabularx environments. The first thing to observe is that they're not dramatically different; this isn't surprising, really, since in both cases the left-hand column is of type l and the five data columns are centered. Nevertheless, there are few important differences, among them the "look" of the "BB" and "DD" columns; their column widths are different from those of the "AA", "CC" and "EE" columns in the tabular* case but not in the tabularx case. I will let on nnow that I "rigged" the table structure so that the tabularx example would have two issues not shared by the tabular* example: (a) the contents of the "BB" column are actually wider than the width calculated by the C column type (note that because the contents are numbers, line breaking isn't possible) and, in consequence, the "BB" header is not centered over the column contents; and (b) there's whitespace to the right of the "EE" column in the tabularx case but, by construction, not in the tabular* case. In my opinion, the tabular* solution looks more balanced.

Summing up, there's a lot more to comparing tabular* and tabularx solutions than simply observing that the former works by changing the inter-column whitespace and that the latter works by changing the column widths. In practice, the two environments can produce fairly similar looking results in some cases and rather different results in others. It's a good idea to be familiar with both approaches and to be able to typeset a given table both ways and then decide which approach works best.

\documentclass{article}
\usepackage{booktabs,tabularx,caption}
\captionsetup{skip=0.33\baselineskip}
\newcolumntype{C}{>{\centering\arraybackslash}X}
% The following macro gets used three times in the body of the document
\newcommand\tabbody{%
\toprule
Time of Day & \multicolumn{5}{c}{Event types} \\
\cmidrule{2-6}
& AA & BB & CC & DD & EE \\
\midrule
Morning & 1.45 & 2.5613444 & 3.67 & 4.78111 & 5.89 \\
Evening & 9.54 & 8.4322222 & 7.32 & 6.21111 & 5.10 \\
\bottomrule}

\begin{document}
\hrule % just to indicate width of text block
\begin{table}[h]
\centering

\caption{A \texttt{tabular} solution}
\begin{tabular}{@{}l*{5}{c}@{}}
\tabbody
\end{tabular}

\bigskip
\caption{A \texttt{tabular*} solution}
\begin{tabular*}{0.85\textwidth}{@{}l @{\extracolsep{\fill}} *{5}{c} @{}}
\tabbody
\end{tabular*}

\bigskip
\caption{A \texttt{tabularx} solution}
\begin{tabularx}{0.85\textwidth}{@{}l *{5}{C}@{}}
\tabbody
\end{tabularx}
\end{table}
\end{document}


# Plain LaTeX tabular

Every column takes its space, the total width of the table is the sum of the columns (plus inter-column space).

***%
\begin{tabular}{p{2cm}p{2cm}p{2cm}}
a a a a a a a a a a a a a a a
& b b b b b b b b b b b b b b b
& c c c c c c c c c c c c c c c
\end{tabular}%
***


# Plain LaTeX tabular*

Every column takes its space, but the table will have a fixed width to the outside.

If this width is too small (3cm), then the following material will overwrite the columns.

***%
\begin{tabular*}{3cm}{p{2cm}p{2cm}p{2cm}}
a a a a a a a a a a a a a a a
& b b b b b b b b b b b b b b b
& c c c c c c c c c c c c c c c
\end{tabular*}%
***


If this width is too wide (0.8\linewidth), then the extra space will be to the right of the table.

***%
\begin{tabular*}{0.8\textwidth}{p{2cm}p{2cm}p{2cm}}
a a a a a a a a a a a a a a a
& b b b b b b b b b b b b b b b
& c c c c c c c c c c c c c c c
\end{tabular*}%
***


It is possible to distribute the extra space between the columns using \extracolsep, but the columns keep their width.

***%
\begin{tabular*}{0.8\textwidth}{@{\extracolsep{\fill} }p{2cm}p{2cm}p{2cm}}
a a a a a a a a a a a a a a a
& b b b b b b b b b b b b b b b
& c c c c c c c c c c c c c c c
\end{tabular*}%
***


# tabularx from the package with the same name

The table has a fixed width to the outside. The space not needed by columns of fixed width is distributed evenly to the columns of type X.

\usepackage{tabularx}
...
***%
\begin{tabularx}{3cm}{XXX}
a a a a a a a a a a a a a a a
& b b b b b b b b b b b b b b b
& c c c c c c c c c c c c c c c
\end{tabularx}%
***


\usepackage{tabularx}
...
***%
\begin{tabularx}{0.8\textwidth}{XXX}
a a a a a a a a a a a a a a a
& b b b b b b b b b b b b b b b
& c c c c c c c c c c c c c c c
\end{tabularx}%
***


• It doesn't really make much sense to use a tabular* environment unless one also provides a @{\extracolsep{\fill}} directive to expand the intercolumn whitespace. I'd say that your two tabular*-related MWEs that do not contain this directive strongly make this point. – Mico Nov 27 '16 at 17:52
• @Mico Sure. The point was to illustrate what tabular* does/doesn't do. Feel free to add your conclusion. – gernot Nov 27 '16 at 17:56