# Automatic column width in tabularx (to minimise blank space)

I have a text table (where the text is often long enough to need to break lines) plus each cell contains several items. However, the number of items in each cell of a row is not the same and, especially in a particular column, this number is usually smaller.

What I want is a type of column which minimises the blank space in the whole table. In this case, then, this column which normally has less items would be narrower. But not only this, the other columns should be wider or narrower depending on how much text is in their cells.

This would be a similar behaviour to the "normal" column types of tabular but with multiple lines in a cell.

See an example of what I mean:

This is just an excerpt of the table. Notice that column 2 is the widest, the next is column 1, followed by column 3, and column 4 is the narrowest. I need a type of column that adjusts these widths automatically depending on the text in all the cells of the table.

Here an example to try it with:

\documentclass[11pt, a4paper, oneside]{report}

\usepackage{lipsum}
\usepackage{tabularx}

\begin{document}

\begin{table}[!htb]
\centering
\caption{Caption.}
\label{label}
\small
\begin{tabularx}{\textwidth}{XXXX}
\hline
• \lipsum[23][1-2] \newline • \lipsum[23][1-3] \newline • \lipsum[23][1-2] & • \lipsum[23] & • \lipsum[3][1-2] \newline • \lipsum[2][1-3] \newline • \lipsum[1][1-2] & • Short and few \\ \hline
• \lipsum[4][1-2] \newline • \lipsum[4][1-3] \newline • \lipsum[4][1-2] & • \lipsum[4] & • \lipsum[3][1-2] \newline • \lipsum[2][1-3] \newline • \lipsum[1][1-2] & • Short and few \\ \hline
• \lipsum[5][1-2] \newline • \lipsum[5][1-3] \newline • \lipsum[5][1-2] & • \lipsum[5] & • \lipsum[2][1-2] \newline • \lipsum[1][1-3] \newline • \lipsum[2][1-2] & • Short and few \\
\hline
\end{tabularx}
\end{table}

\end(document)

• tabulary tries to do this (with mixed results, but worth a try) May 23 '20 at 10:32
• please always provide a complete small test document to show the problem and allow people to test answers. No one is going to want to have to type in the table from an image to test a tabulary answer. May 23 '20 at 10:34
• @DavidCarlisle, thanks. I added the example. I will now try tabulary, thanks :-) May 23 '20 at 10:49

• I understand your objective as follows: Have LaTeX determine the relative widths of the X-type columns of a tabularx environment automatically, in a way that minimizes the total height of the environment (the width being set ex ante to \textwidth, right?). This objective is not only ambitious (which isn't a bad thing per se, by the way), but it may also result in a typographically inferior outcome. Why?

• If a given column contains very little material, its width should generally not be made smaller than some fixed value, for typographic and aesthetic reasons. For instance, even though the 4th column of your example tabularx environment contains almost no material, its minimum acceptable width should probably be no less than the width of the header, here: "Header 4". An even if it's judged that a line break in the header cell of the fourth column is permissible, the width should likely be no smaller than what's necessary to place 5- and 6-letter words on a line by themselves. (My rule of thumb is that it must be feasible to place the non-breakable word "through" on a line without creating a spill-over into the next column, or into the right-hand margin.) In general, then, some preliminary fiddling will be unavoidable in order determine which columns (if any) should be given fixed widths.

• If a tabularx environment has n X-type columns of varying (relative) widths w_i, i=1,...,n, only n-1 widths are free since the widths must also satisfy \sum_i w_i = n.

• In practice, even if a tabularx environment contains 4 or 5 columns in total, 1 or 2 of the columns may look best if they're assigned a fixed width. This reduces the number of X-type columns by 1 or 2 as well. For instance, your table contains 4 columns, but 1 column should be given a fixed width because of the aforementioned ex ante considerations. This leaves just 3 type-X columns, and thus only 2 free parameters. I will blithely assert that most people can easily find satisfactory values for w_1, w_2, and w_3 within 2 or 3 iterations even if they set w_1=w_2=w_3=1 as the starting point.

For the example at hand, I arrived at w_1=0.6, w_2=1.3, and hence w_3=1.1 after just 2 iterations, by applying no more than basic "ocular regression" analysis. Happily, the table fits inside the text block (assuming margins of 2.5cm all around). Some additional fiddling with w_1, w_2, and w_3 will almost certainly result in a more compact appearance. However, I would argue that such an effort would be utterly wasted as the table, as it is, is so large that it will likely reside on a page all by itself anyway.

\documentclass[11pt, a4paper, oneside]{report}

\usepackage[margin=2.5cm]{geometry} % set suitable page size parameters
\usepackage{lipsum}

\usepackage{tabularx,ragged2e,booktabs,caption}
\newcolumntype{P}[1]{>{\RaggedRight\hspace{0pt}}p{#1}}
\newcolumntype{L}[1]{>{\RaggedRight\hsize=#1\hsize\linewidth=\hsize}X}

\newlength\mylength

\usepackage{enumitem}
% create a bespoke itemize-like environment:
\newlist{myitemize}{itemize}{1}
\setlist[myitemize]{label =\textbullet, nosep, wide=0pt,
before=\begin{minipage}[t]{\hsize},
after =\end{minipage}}

\begin{document}

\begin{table}[htbp]
\small
\captionsetup{size=small,skip=0.333\baselineskip}
\caption{Caption.}\label{label}
% measure width of col. 4:
\setlength\tabcolsep{4pt}
\begin{tabularx}{\textwidth}{@{} L{0.6}L{1.3}L{1.1} P{\mylength} @{}}
\toprule
\midrule
\begin{myitemize}
\item \lipsum[23][1-2]
\item \lipsum[23][1-3]
\item \lipsum[23][1-2]
\end{myitemize} &
\begin{myitemize}
\item \lipsum[23]
\end{myitemize} &
\begin{myitemize}
\item \lipsum[3][1-2]
\item \lipsum[2][1-3]
\item \lipsum[1][1-2]
\end{myitemize} &
\begin{myitemize}
\item Short and few
\end{myitemize}\\
\midrule

\begin{myitemize}
\item \lipsum[4][1-2]
\item \lipsum[4][1-3]
\item \lipsum[4][1-2]
\end{myitemize} &
\begin{myitemize}
\item \lipsum[4]
\end{myitemize} &
\begin{myitemize}
\item \lipsum[3][1-2]
\item \lipsum[2][1-3]
\item \lipsum[1][1-2]
\end{myitemize} &
\begin{myitemize}
\item Short and few
\end{myitemize} \\
\midrule

\begin{myitemize}
\item \lipsum[5][1-2]
\item \lipsum[5][1-3]
\item \lipsum[5][1-2]
\end{myitemize} &
\begin{myitemize}
\item \lipsum[5]
\end{myitemize} &
\begin{myitemize}
\item \lipsum[2][1-2]
\item \lipsum[1][1-3]
\item \lipsum[2][1-2]
\end{myitemize} &
\begin{myitemize}
\item Short and few
\end{myitemize} \\
\bottomrule
\end{tabularx}
\end{table}

\end{document}

• Wow, thanks. I don't yet fully understand the definitions of \newcolumntype but I guess that the weights you give to the L columns add up to 3 because there are 3 of them, right? May 23 '20 at 12:41
• @Miquel - You're welcome. The main aspect of the \newcolumntype definitions is that they insert the directive \RaggediRight: In narrow columns, it's often not feasible to achieve satisfactory full justification; using "ragged-right" is often better. \RaggedRight, unlike \raggedright, permits hyphenation. In addition, the L column type is set up to make it easy to enter the intended relative width. On your question: indeed, the some of the (relative) widths of the three columns of type X (or L) must be equal to the number of columns (3).
– Mico
May 23 '20 at 12:52
• What is the difference (or the advantage) between using the defined itemize-like environment and just writing the dot, here? May 23 '20 at 14:52
• @Miquel - Bespoke itemize-like like environments have the advantage of letting you redefine virtually all aspects of the appearance of the lists. In contrast, if you choose to hard-code things like bullet points, you'll find it exceedingly tedious, to adopt a different style should you ever need to do so.
– Mico
May 23 '20 at 14:55
• Thanks :-) As the table is too long anyway (it doesn't fit in a page and I have to make it landscape), what I did was to use tabulary to check how it looks and, as I liked the distribution, I measured the different sizes of the columns to have the weights for the different columns :-P May 23 '20 at 15:15