The Problem
I want to create a table with an exact width. So I thought I'd use the
tabular*
environment. Then I realised, that it might be a little
more difficult than I imagined in the beginning. The problem is the
horizotal alignment/positioning: \tabcolsep
and \arrayrulewidth
change the positioning.
No additional packages loaded
Consider the following:
\documentclass[varwidth=3.5cm,margin=2mm]{standalone}
\setlength{\arrayrulewidth}{.6pt}
\setlength{\tabcolsep}{0pt}
\begin{document}
\textbf{No packages}\par\vspace{5pt}
\begin{tabular*}{14mm}{ |@{} p{7mm} @{}|@{} p{7mm} @{}| } % 1: shifts---because of the vlines
\hline
\hspace{2pt}foo & \hspace{2pt}bar
\end{tabular*} (1)
\par\vspace{5pt}
\verb|\tabcolsep=0pt|\par
\begin{tabular*}{14mm}{ | p{7mm} | p{7mm} | } % 2: default, alignment is correct
\hline
\hspace{2pt}foo & \hspace{2pt}bar
\end{tabular*} (2) default
\begin{tabular*}{14mm}{% 3: manually corrected outer vertical line
@{\kern.5\arrayrulewidth}|@{\kern-\arrayrulewidth}%
p{7mm} | p{7mm}%
@{\kern-.5\arrayrulewidth}| }
\hline
\hspace{2pt}foo & \hspace{2pt}bar
\end{tabular*} (3) fixed1
\par\vspace{5pt}
\verb|\tabcolsep=2pt|\par
\setlength{\tabcolsep}{2pt}
\begin{tabular*}{14mm}{ | p{7mm} | p{7mm} | } % 4: default, alignment is NOT correct
\hline
foo & bar
\end{tabular*} (4) default
\begin{tabular*}{14mm}{% 5: manually corrected with tabcolsep active
@{\kern.5\arrayrulewidth}|%
p{\dimexpr 7mm-2\tabcolsep-.5\arrayrulewidth\relax}%
|%
p{\dimexpr 7mm-2\tabcolsep-.5\arrayrulewidth\relax}%
|}
\hline
foo & bar
\end{tabular*} (5) fixed2
\begin{tabular*}{14mm}{% 6: manually corrected(2) with tabcolsep active
p{\dimexpr 7mm-2\tabcolsep-0 \arrayrulewidth\relax}%
p{\dimexpr 7mm-2\tabcolsep-.5\arrayrulewidth\relax}%
|}
\hline
foo & bar
\end{tabular*} (6) fixed3
\end{document}
First impression: the left vline is not aligned with the
table border. As one can see, I first tried to get rid of all
\tabcolsep
s manually (1). This still has the widths of the vlines
though. Curiously, the default behaviour with \tabcolsep=0pt
does
manage shifts caused by the vlines (2). One can fix the ugly outer
vlines (not matching the edge of the table) manually (3). But this
still leaves the problem of horizontal spacing in the cells. One could
put a shifted parbox in there. A lot of work for many cells. So it
might be better to use \tabcolsep
. If I do, the default behaviour
is shown in (4). Not working correctly, so one has to start fixing
again. Curiously, this time one has to consider the width of the
vlines in the fix (5). Obviously this is the better solution compared
to (3). But this leads to potentially many manual adjustments with
big tables, especially if there are not vlines between every column,
as this has to be considered (6).
With package array
Trying to use one of the packages that should improve the behaviour
of tables, I tried the array
package:
\documentclass[varwidth=3.5cm,margin=2mm]{standalone}
\usepackage{array}
\setlength{\arrayrulewidth}{.6pt}
\setlength{\tabcolsep}{0pt}
\begin{document}
\textbf{array package}\par\vspace{5pt}
\begin{tabular*}{14mm}{ |@{} p{7mm} @{}|@{} p{7mm} @{}| } % 1: shifts---because of the vlines
\hline
\hspace{2pt}foo & \hspace{2pt}bar
\end{tabular*} (1)
\par\vspace{5pt}
\verb|\tabcolsep=0pt|\par
\begin{tabular*}{14mm}{ | p{7mm} | p{7mm} | } % 2: default, alignment is correct
\hline
\hspace{2pt}foo & \hspace{2pt}bar
\end{tabular*} (2) default
\begin{tabular*}{14mm}{% 3: manually corrected outer vertical line
|@{\kern-\arrayrulewidth}%
p{7mm}%
@{\kern-.5\arrayrulewidth}|@{\kern-.5\arrayrulewidth}%
p{7mm}%
@{\kern-\arrayrulewidth}| }
\hline
\hspace{2pt}foo & \hspace{2pt}bar
\end{tabular*} (3) fixed1
\par\vspace{5pt}
\verb|\tabcolsep=2pt|\par
\setlength{\tabcolsep}{2pt}
\begin{tabular*}{14mm}{ | p{7mm} | p{7mm} | } % 4: default, alignment is NOT correct
\hline
foo & bar
\end{tabular*} (4) default
\begin{tabular*}{14mm}{% 5: manually corrected with tabcolsep active
|%
p{\dimexpr 7mm-2\tabcolsep-1.5\arrayrulewidth\relax}%
|%
p{\dimexpr 7mm-2\tabcolsep-1.5\arrayrulewidth\relax}%
|}
\hline
foo & bar
\end{tabular*} (5) fixed2
\begin{tabular*}{14mm}{% 6: manually corrected(2) with tabcolsep active
p{\dimexpr 7mm-2\tabcolsep-0\arrayrulewidth\relax}%
p{\dimexpr 7mm-2\tabcolsep-1\arrayrulewidth\relax}%
|}
\hline
foo & bar
\end{tabular*} (6) fixed3
\end{document}
The left alignment of the vline seems to be corrected automatically,
good. Sadly, this isn't really improving the overall result:
To the right, the same issues appear. (1) is the same as before
with corrected left vline. (2) shows the default behaviour with
\tabcolsep=0pt
. Again, manual fixing is needed (3). Better
is to use \tabcolsep
though. The default behaviour is shown in
(4). This obviously has to be fixed as well (5). Here the situation
is even worse than without the arrays
package. One has to consider
whether the column is an outer column or not, in order to fix the
parbox widths. This doesn't get better if some vlines are not used
(6). tabularx
result looks similar. There is always the need to
adjust manually.
tabularx package
\documentclass[varwidth=3.5cm,margin=2mm]{standalone}
\usepackage{tabularx}
\setlength{\arrayrulewidth}{1pt}
\setlength{\tabcolsep}{2pt}
\begin{document}
\textbf{tabularx package}\par\vspace{5pt}
\begin{tabular*}{14mm}{% 1: target layout
|%
p{\dimexpr 7mm-2\tabcolsep-1.5\arrayrulewidth\relax}%
|%
p{\dimexpr 7mm-2\tabcolsep-1.5\arrayrulewidth\relax}%
|}
\hline
foo & bar
\end{tabular*} (1) target
\begin{tabularx}{14mm}{ |X|X| }% default without manual sizing
\hline
foo & bar
\end{tabularx} (2) default1
\begin{tabularx}{14mm}{ |>{\hsize=7mm}X|X| }
\hline
foo & bar
\end{tabularx} (3) default2
\begin{tabularx}{14mm}{ |>{\hsize=\dimexpr7mm-2\tabcolsep-1.5\arrayrulewidth\relax}X|X| }
\hline
foo & bar
\end{tabularx} (4) fixed
\end{document}
This does some things better (e.g. right vline is always aligned), but one still has to do manual calculations based on vlines before or after...
Correct tables by default?
I would like to use a normal environment without the need to adjust it manually. Something like
\newlength{\mylength}
\def\mylength{-2\tabcolsep-.5\arrayrulewidth}
could work, if I can make them sensitive to the context vlines. Using
array
,
\newcolumntype{P}[1]{>{\raggedright\arraybackslash}p{\dimexpr#1-2\tabcolsep-\arrayrulewidth\relax}}
could work almost automated, if it could see surrounding vlines. I don't want to create a ton of column types and take care of which one to take (outer, inner column, surrounded by zero, one, two vlines).
How can I get a table of the predefined width without manual interaction?
tabularx
(which, incidentally, loadsarray
)?array
for my tests.\begin{tabular*}{14mm}{|@{}p{7mm}@{\hspace*{-2\arrayrulewidth}}|@{}p{7mm}@{\hspace*{-\arrayrulewidth}}|}
then the gaps disappear. Same for\begin{tabular*}{\dimexpr14mm+3\arrayrulewidth}{|@{}p{7mm}@{}|@{}p{7mm}@{}|}
, in which case the width between the vlines is 7mm each.