14

I want some columns in my tables to have a minimal column width, that should always be maintained, even if the content is smaller, but increased when the content is wider.

Bounty-related update: @Sandy G's answer produces the desired behavior, but I want it to be a column type so that I can specify it like this:

\documentclass{article}
\begin{document}
  \begin{tabular}{m{2cm}m{2cm}m{1cm}m{1cm}}
    Longer entry here&2&3&4\\
    5&6&Longer entry here&8
  \end{tabular}
\end{document}
1
  • I'm awarding the bounty to Steven's solution, because the bounty was explicitly for a solution that defines a new column-type. However, credit is also due to Sandy G's solution, which was however already there before the bounty started
    – sheß
    Mar 11, 2019 at 8:55

4 Answers 4

15
+50

See ADDENDUM and BONUS

First, the original approach.

Here is a \newcolumntype solution, except that, for a reason that I should know but I don't, it won't work in the last column of the tabular. I'm sure David C. could tell me off the cuff why.

So I've provided C{}, L{}, and R{} column types for specifying a minimum width, and an Q column type to use for a phantom, to get around the deficiency I initially cited.

\documentclass{article}
\usepackage{tabularx,stackengine}
\newcolumntype{L}[1]{>{\minwd l{#1}}l<{\endminwd}}
\newcolumntype{C}[1]{>{\minwd c{#1}}c<{\endminwd}}
\newcolumntype{R}[1]{>{\minwd r{#1}}r<{\endminwd}}
\def\minwd#1#2#3\endminwd{\stackengine{0pt}{#3}{\rule{#2}{0pt}}{O}{#1}{F}{F}{L}}
\newcolumntype{Q}{@{}c@{}}
\begin{document}
\begin{tabular}{|C{1.2cm}|C{1.2cm}|R{2cm}|l|}
a & a& b& c\\
aaaaaaaaaaaaaaaaa& aa& bb& cc\\
\end{tabular}
\bigskip


\begin{tabular}{|C{1.2cm}|C{1.2cm}|R{2cm}|L{1.5cm}|Q}
a & a& b& c&\\
aaaaaaaaaaaaaaaaa& aa& bb& cc&\\
\end{tabular}
\end{document}

enter image description here


ADDENDUM

Apparently the way to overcome the deficiency I noted in my original solution is to use \collectcell:

\documentclass{article}
\usepackage{tabularx,stackengine,collcell}
\let\endminwd\relax
\newcolumntype{L}[1]{>{\collectcell\xminwd l{#1}}l<{\endminwd\endcollectcell}}
\newcolumntype{C}[1]{>{\collectcell\xminwd c{#1}}c<{\endminwd\endcollectcell}}
\newcolumntype{R}[1]{>{\collectcell\xminwd r{#1}}r<{\endminwd\endcollectcell}}
\def\minwd#1#2#3\endminwd{\stackengine{0pt}{#3}{\rule{#2}{0pt}}{O}{#1}{F}{F}{L}}
\newcommand\xminwd[1]{\minwd#1}
\begin{document}
\begin{tabular}{|C{1.2cm}|C{1.2cm}|R{2cm}|L{1.5cm}|}
a & a& b& c\\
aaaaaaaaaaaaaaaaa& aa& bb& cc\\
\end{tabular}
\end{document}

enter image description here

And just for fun, if you set the vertical measure of the \rule to something nonzero, say 1pt, you can see how the rule comes into play:

enter image description here


BONUS

I realized the technique could be used for creating a D column for aligning a specified number of trailing decimal places. EDITED to handle decimal free inputs.

\documentclass{article}
\usepackage{tabularx,stackengine,collcell}
\let\endecm\relax
\newcolumntype{D}[1]{>{\collectcell\Decm l{#1}}r<{..\endDecm\endcollectcell}}
\def\decm#1#2#3.#4.#5\endDecm{#3.\stackengine{0pt}{#4}{\rule{#2\wd0}{0pt}}{O}{#1}{F}{F}{L}}
\newcommand\Decm[1]{\setbox0=\hbox{0}\decm#1}
\begin{document}
\begin{tabular}{|D{3}|D{2}|D{4}|}
10.345 & 410.34 & 1310.34\\
10 & 11 & 12.\\
210.34 & 1210.3 & 310.3456\\
\end{tabular}
\end{document}

enter image description here

12

This could be done by placing a row of 0pt \rules with a negative row separator (for proper vertical alignment).

enter image description here

In the example, columns 1 and 2 have minimum width 2cm, while columns 3 and 4 have minimum width 1cm.

\documentclass{article}

\begin{document}
\[
\begin{tabular}{cccc}
\rule{2cm}{0pt}&\rule{2cm}{0pt}&\rule{1cm}{0pt}&\rule{1cm}{0pt}\\[-\arraystretch\normalbaselineskip]]
Longer entry here&2&3&4\\
5&6&Longer entry here&8
\end{tabular}
\]
\end{document}

Update: By placing the \rule in a macro, you can adjust the fixed minimum in the document body similarly to a column type.

enter image description here

Here is the code:

\documentclass{article}

\newcommand{\fixedmin}[1]{\rule{#1}{0pt}&\rule{#1}{0pt}&\rule{#1}{0pt}&\rule{#1}{0pt}\\[-\arraystretch\normalbaselineskip]}

\begin{document}

\noindent Here is a table with fixed minimum width 2 cm.
\[
\begin{tabular}{cccc}\fixedmin{2cm}
Longer entry here&2&3&4\\
5&6&Longer entry here&8
\end{tabular}
\]

\noindent Here is a table with fixed minimum width 1 cm.
\[
\begin{tabular}{cccc}\fixedmin{1cm}
Longer entry here&2&3&4\\
5&6&Longer entry here&8
\end{tabular}
\]

\noindent Here is a table with no fixed minimum width.
\[
\begin{tabular}{cccc}
Longer entry here&2&3&4\\
5&6&Longer entry here&8
\end{tabular}
\]

\end{document}
4
  • 2
    Great. Is there an easy way to make this a column type?
    – sheß
    Nov 22, 2017 at 7:22
  • Nice update. I still hope though that someone will find a way to make this a columntype
    – sheß
    Mar 6, 2019 at 15:23
  • That's a nice low-tech solution. Mar 6, 2019 at 19:22
  • Instead of \rule it's cleaner to just use \hspace*.
    – user202729
    Feb 4 at 0:38
8

Here's a way to do it using the collcell package. The idea is to measure the content of the cell and then add rules to make up the deficit where appropriate. I've made versions for c, r and l columns. The vertical lines are just there to show the fixed width columns.

\documentclass{article}
\usepackage{array,calc,collcell}
\newlength{\fwlen}
\newcolumntype{C}[1]{>{\setlength{\fwlen}{#1}\collectcell\fixedCwidth}c<{\endcollectcell}}
\newcolumntype{R}[1]{>{\setlength{\fwlen}{#1}\collectcell\fixedRwidth}r<{\endcollectcell}}
\newcolumntype{L}[1]{>{\setlength{\fwlen}{#1}\collectcell\fixedLwidth}l<{\endcollectcell}}
\makeatletter
\newcommand{\fixedCwidth}[1]{\setlength{\@tempdima}{\widthof{#1}}\ifdim\@tempdima>\fwlen #1\else\setlength{\@tempdimb}{(\fwlen-\@tempdima)/2}\rule{\@tempdimb}{0pt}#1\rule{\@tempdimb}{0pt}\fi}
\newcommand{\fixedLwidth}[1]{\setlength{\@tempdima}{\widthof{#1}}\ifdim\@tempdima>\fwlen #1\else\setlength{\@tempdimb}{\fwlen-\@tempdima}#1\rule{\@tempdimb}{0pt}\fi}
\newcommand{\fixedRwidth}[1]{\setlength{\@tempdima}{\widthof{#1}}\ifdim\@tempdima>\fwlen #1\else\setlength{\@tempdimb}{\fwlen-\@tempdima}\rule{\@tempdimb}{0pt}#1\fi}
\makeatother
\begin{document}


\begin{tabular}{|C{1cm}|L{1cm}|R{1cm}|C{1cm}|C{1cm}|}
123 &   123 &   123 &   123 & This is a wider column\\
5   &   6   &   6   &   8 & 8
\end{tabular}

\end{document}

output of cod

1

To do it properly, you need a minimum width and a maximum width of each column. You required the minimum width in your question. I'd say, it is better to have a maximum width, because otherwise your tabular might run out of the margin.

\documentclass{article}
\usepackage{array} 
\usepackage{varwidth}% varwidth defines a new column type V.

\begin{document}
\begin{tabular}{*{4}{V{4cm}}}
\hspace*{2cm} & \hspace*{2cm} & \hspace*{1cm} & \hspace*{1cm}\\[-1em]
    Longer entry here&2&3&4\\
    5&6&Longer entry here, which gets wrapped finaly&8\\
  \end{tabular}
\end{document}

There are two small tricks.

First, the varwidth package defines a new column type, but this is not documented in the manual, I found it here: https://texfaq.org/FAQ-varwidcol

V{4cm}sets the maximum width of a column.

Second: we need a minimum width. We just can take an empty line of the tabular and fill it with empty spaces of the needed minimum width. To hide this line, I inserted \\[-1em], which you need to adapt in your use case. I suggest to put it as first line of the tabular, followed by the head of the tabular, not the other way round.

Hopefully it works in your use case!

pic of tabular

2
  • Thanks for your effort. You seem to be answering a slightly different question though. Can you elaborate on what you mean by "to do it properly"? How is ruining out of the margins a problem related to setting a minimum width? Doesn't this also happen with a plain \begin{tabular}{cccc}-table?
    – sheß
    Mar 6, 2019 at 22:11
  • @sheß Yes, any column of the types c or l or r can become much to broad. So I prefer the p or b or m column type!
    – Keks Dose
    Mar 6, 2019 at 22:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .