# Balance tabular columns automatically?

How to balance the columns of such declaration:

\begin{tabularx}{\linewidth}{
>{\hsize=0.4\hsize}X% 10% of 4\hsize
>{\hsize=1.6\hsize}X% 30% of 4\hsize
>{\hsize=0.4\hsize}X% 10% of 4\hsize
>{\hsize=1.6\hsize}X% 30% of 4\hsize
}
\end{tabularx}


Obviously the values 0.4 and 1.6 have to be adjusted automatically at build time...

Example:

     .--------- Same width ---------------.
|                                    |
<----+--->                            <---+---->
┌────────┬────────────────────────────┬────────┬───────────────────────────┐
│ A      │ B                          │ A      │ B                         │
├────────┼────────────────────────────┼────────┼───────────────────────────┤
│ 132132 │ Sed rutrum elit quis neque │ 42     │ Cras porta                │
└────────┴────────────────────────────┴────────┴───────────────────────────┘
<------------+--------------->        <-------------+------------->
|                                      |
'------------- Same width -------------'


Where the odd column have size A and the even ones a size B? With this I guarantee that column 1 and 3 have always the same size, and column 2 and 4 are equally distributed in space.

In other words, the min width of the columns are determined as follow:

min_widths[0] = min_widths[2] = max(map(width, columns[0] + columns[2]))
min_widths[1] = min_widths[3] = max(map(width, columns[1] + columns[3]))


Then everything is stretch to fit in the \linewidth:

if sum(min_widths) > \linewidth:
% Attempts to wrap some text and reduce the column sizes
else:
widths = map(lambda x: x * (\linewidth / sum(min_widths), min_widths)


Good parameters for such feature would be:

- Column alignment: left, center, right, raggedleft, raggedright
- Maximum width: e.g. 10em
- Minimum width: e.g. 0em
- Desired width ratio: 1
- Automatic wrapping: yes, no

• It is not very clear (to me) , what you like to have ... but see if you looking for something like this: \documentclass{article} \usepackage{tabularx} \begin{document} \begin{tabularx}{\linewidth}{*{2}{>{\hsize=0.4\hsize}X >{\hsize=1.6\hsize}X} } \hline xxx xxx & xxx xxx xxx xxx xxx xxx xxx xxx & xxx xxx & xxx xxx xxx xxx xxx xxx xxx xxx\\ \hline \end{tabularx} \end{document} Aug 5, 2019 at 13:30
• I have added an example Aug 5, 2019 at 13:41
• Why do you want to use tabularx for this? You could simply set the column type to p{some-calculated-width}. Aug 5, 2019 at 13:45
• Because the table should have the width \linewidth Aug 5, 2019 at 13:46
• The X column type is nothing but a p-type column for which LaTeX takes on the job of calculating the absolute width of the column should be, given information about the overall width of the tabularx environment, the number of X-type columns, and the number and width of any other columns. Since X columns, like p columns, are set up to allow automatic line breaking, it's not clear to me if there's enough information contained in the setup you've described to perform the required relative and absolute width calculations.
– Mico
Aug 5, 2019 at 13:58

EDIT 20190807 At the end of the answer, I have included the code I recommend, an amalgamation of Zarko’s and my answer.

You may have a tabular to use the whole linewidth by calculating the width of p{}-columns as fractions of the linewidth. Just ensure that the total number of column widths accumulate to the linewidth. You have to subtract the correct number of tabcolseps, which is two per column (total eight for four columns). If you have vertical rules, you also have to subtract the correct numbers of arrayrulewidths.

I have ‘improved’ the previous example. If you look at the definition of an A-column, it now reads:

\newcolumntype{A}{>{\RaggedRight\arraybackslash}p{\dimexpr(1\textwidth)*25/100/2-1.5\tabcolsep\relax}}

1. If you prefer centred or right aligned columns, you change \RaggedRight to \Centering or \RaggedLeft.
2. If you need a tabular where the total width is less than the full linewidth, you change (1\linewidth) to the correct fraction. For example, if you need a tabular 80 per cent of the linewidth, you use (0.8\linewidth).
3. The formula 25/100/2 is the relative width of the A-column, here 25%. This number is meant to be set so that the total of the newcolumntype is 100. Therefore, the B-column use 75/100. The last digit is the number of A-or B-columns.
4. If you remove the left and right side bearings, (@{}), the number of tabcolseps to subtract will be two less than the total number of tabcolsepts. If you have four columns, you have to subtract six, if you have six columns, you have so subtract ten, etc. The formula will be -(2\tabcolsep-(\tabcolsep/<no. col.type>)). If you have three A-columns, you have to subtract -(2\tabcolsep-(\tabcolsep/3)).
5. If you use vertical rules, you have to distribute the number of arrayruleswidth correctly, too. I leave it to you as an exercise to do that.

Above, I have assumed you will use equal number of each column types (ABAB, ABBA, ABBBAA etc.). In an automated calculation you have to take into consideration that the number of column types not necessarily will be the same number (you may have ABBAA, ABABA, etc.). So you will easily end up with a very complicated package. Probably it is better to use a calculator, or pen and paper, to fix the column width. Obviously, it is much faster than program it in LaTeX.

NB! I emphasise that tabularx and tabulary already do all the maths for you. However, have a look at section 4.3 in the tabularx-manual.

Below I have enclosed code for a tabular with six columns:

\documentclass{article}
\usepackage{array, booktabs, ragged2e}

\newcolumntype{A}{>{\RaggedRight\arraybackslash}p{\dimexpr(1\textwidth)*25/100/3-(2\tabcolsep-(\tabcolsep/3))\relax}}
\newcolumntype{B}{>{\Centering\arraybackslash}p{\dimexpr(1\textwidth)*75/100/3-(2\tabcolsep-(\tabcolsep/3))\relax}}
\usepackage{showframe}

\renewcommand*\ShowFrameColor{\color{red}}
\renewcommand*\ShowFrameLinethickness{.4pt}

\setlength{\tabcolsep}{2pt}

\begin{document}
{\centering
\begin{tabular}{@{}ABABBA@{}}

\toprule
A   &    B  &   A   &   B &   A   &   B\\
\midrule
Short left alig\-ned column & Wide centered column, which has lots of text & Short left alig\-ned column & Wide centered column, which has lots of text  & Wide centered column, which has lots of text & Short left alig\-ned column  \\
\bottomrule

\end{tabular}%
}
\end{document}


Recommended example code

\documentclass{article}
\usepackage{booktabs, ragged2e}
\usepackage{tabularx}
\newcolumntype{D}{>{\small\RaggedRight\arraybackslash\hsize=0.4\hsize}X}
\newcolumntype{E}{>{\small\Centering\arraybackslash\hsize=1.6\hsize}X}
\setlength{\tabcolsep}{1.5pt}

\begin{document}

\noindent\begin{tabularx}{\linewidth}{@{}DEDEED@{}}
\toprule
D   &    E  &   D   &   E  &   E   &   D\\
\midrule
Short left alig\-ned column & Wide centered column, which has lots of text & Short left alig\-ned column & Wide centered column, which has lots of text  & Wide centered column, which has lots of text & Short left alig\-ned column  \\
\bottomrule
\end{tabularx}
\end{document}


As I understand the question, tables should have a width equal to the width of the text. So, I don't see any advantages (maybe due to my vacation?) why not to use tabularx as I suggested in my comment below question:

\documentclass{article}
\usepackage{tabularx}

\begin{document}
\begin{table}[ht]
\begin{tabularx}{\linewidth}{|*{2}{>{\hsize=0.4\hsize}X| >{\hsize=1.6\hsize}X|} }
\hline
xxx xxx & xxx xxx xxx xxx xxx xxx xxx xxx
& xxx xxx & xxx xxx xxx xxx xxx xxx xxx xxx\\
\hline
\end{tabularx}
\caption{Four column}
\end{table}
\begin{table}[ht]
\begin{tabularx}{\linewidth}{|*{3}{>{\hsize=0.4\hsize}X| >{\hsize=1.6\hsize}X|} }
\hline
xxx xxx & xxx xxx xxx xxx xxx xxx xxx xxx
& xxx xxx & xxx xxx xxx xxx xxx xxx xxx xxx
& xxx xxx & xxx xxx xxx xxx xxx xxx xxx xxx\\
\hline
\end{tabularx}
\caption{Sixt column}
\end{table}
\end{document}


(red lines indicate text borders)

• @Sveinung, oh, now I see OP's confusion about purpose of the tabularx. Aug 6, 2019 at 11:52
• And if you have to use multicolumn (and multirow?), section 4.3 in the tabularx-manual has a warning. However, I have, as far as I can remember, never run into any issues. I were the OP, I would have chosen to use tabularx as you describe, but defining new columntypes (as I have done). Aug 6, 2019 at 12:01
• @Sveinung, with the recent multirow you can use = option and with it preserve column specification, with \multicolumn you should be aware how the column widths are determined (about this you can find many answers on this site) Aug 6, 2019 at 12:09
• @Sveinung, thank you very much for editing of my answer. Now MWE is complete and language improved! Aug 6, 2019 at 21:09
• In your case you specified the size of each columns. I do want to LaTeX to determine automatically the width of the columns based on the content. The table with the four columns xxxx|xxxxxxxx|x|xxxx| will have the widths 4, 8, 4, 8 so the first column width is the maximum width of the column 1 and 3: min(4, 1)=4 Aug 7, 2019 at 6:56