3

Question

I'm using the following manual code to create a table with custom rules and spacing. However, there are two problems with it:

  1. It is inconvenient to manually add the \topspace after every rule and and \bottomspace before every rule.
  2. I would like to use the standard \toprule, \midrule, \bottomrule commands and the standard | column type within the table, without overwriting their appearance globally.

How can I define a custom mytable environment that automatically inserts the custom spacing around rules and overwrites the rule widths temporarily, resulting in the same visual output as my manual code?

Current code

\documentclass{article}
\usepackage{tabularx}

\newcommand{\PreserveBackslash}[1]{\let\temp=\\#1\let\\=\temp}
\newcolumntype{:}{!{\vrule width 0.05em}}
\newcolumntype{C}[1]{>{\PreserveBackslash\centering}p{#1}}
\newcolumntype{R}[1]{>{\PreserveBackslash\raggedleft}p{#1}}
\newcolumntype{L}[1]{>{\PreserveBackslash\raggedright}p{#1}}
\makeatletter
\def\hlinewd#1{%
\noalign{\ifnum0=`}\fi\hrule \@height #1 \futurelet
\reserved@a\@xhline}
\makeatother
\newcommand\topspace{\rule{0pt}{2.6ex}}
\newcommand\bottomspace{\rule[-1.2ex]{0pt}{0pt}}

\begin{document}
\begin{tabular}{: L{6em} : C{6em} C{6em} C{6em} :}
\hlinewd{0.08em}
\textbf{Column} & \textbf{First} & \textbf{Second} & \textbf{Third}\topspace\bottomspace \\
\hlinewd{0.05em}
First  & $ 3 $ & $ 5 $ & $ 2 $\topspace \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third  & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $\bottomspace \\
\hlinewd{0.05em}
Average & $ 2 $ & $ 2 $ & $ 1 $\topspace\bottomspace \\
\hlinewd{0.08em}
\end{tabular}
\end{document}

table with custom rules and spacing

Desired outcome

\documentclass{article}
\usepackage{tabularx}

% TODO: Define custom mytable environment here...

\begin{document}
\begin{mytabular}{| L{6em} | C{6em} C{6em} C{6em} |}
\toprule
\textbf{Column} & \textbf{First} & \textbf{Second} & \textbf{Third} \\
\midrule
First  & $ 3 $ & $ 5 $ & $ 2 $ \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third  & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $ \\
\midrule
Average & $ 2 $ & $ 2 $ & $ 1 $ \\
\bottomrule
\end{mytabular}
\end{document}

table with custom rules and spacing

2
  • 1
    For reference, booktabs encourages the avoidance of vertical rules, as the columnar representation within a table necessarily defines the structure properly.
    – Werner
    Sep 9 at 16:51
  • @Werner Thanks, I'm aware :) There are good reasons for me to use vertical rules, as it's helpful for grouping a subset of columns together and it's the industry standard in my field.
    – danijar
    Sep 9 at 17:00
3

It’s easy peasy with booktabs environment of the new LaTeX3 package tabularray:

\documentclass{article}

\usepackage{tabularray}
\UseTblrLibrary{booktabs}

\NewColumnType{L}[1]{Q[l,#1]}
\NewColumnType{C}[1]{Q[c,#1]}
\NewColumnType{R}[1]{Q[r,#1]}

\begin{document}

\begin{booktabs}{| L{6em} | C{6em} C{6em} C{6em} |}
\toprule
\textbf{Column} & \textbf{First} & \textbf{Second} & \textbf{Third} \\
\midrule
First  & $ 3 $ & $ 5 $ & $ 2 $ \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third  & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $ \\
\midrule
Average & $ 2 $ & $ 2 $ & $ 1 $ \\
\bottomrule
\end{booktabs}

\bigskip

\begin{booktabs}{
  colspec = {| L{6em} | C{6em} C{6em} C{6em} |},
  row{1} = {font = \bfseries},
}
\toprule
Column & First & Second & Third \\
\midrule
First  & $ 3 $ & $ 5 $ & $ 2 $ \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third  & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $ \\
\midrule
Average & $ 2 $ & $ 2 $ & $ 1 $ \\
\bottomrule
\end{booktabs}

\end{document}

enter image description here


Also an updated example with customized vertical space:

\documentclass{article}

\usepackage{tabularray}
\UseTblrLibrary{booktabs}

\NewColumnType{L}[1]{Q[l,#1]}
\NewColumnType{C}[1]{Q[c,#1]}
\NewColumnType{R}[1]{Q[r,#1]}

\usepackage{environ}
\NewEnviron{mytabular}[1]{%
  \setlength{\aboverulesep}{1ex}%
  \setlength{\belowrulesep}{1.5ex}% 
  \begin{booktabs}[expand=\BODY]{#1}
    \BODY
  \end{booktabs}
}

\begin{document}

\begin{mytabular}{| L{6em} | C{6em} C{6em} C{6em} |}
\toprule
\textbf{Column} & \textbf{First} & \textbf{Second} & \textbf{Third} \\
\midrule
First  & $ 3 $ & $ 5 $ & $ 2 $ \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third  & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $ \\
\midrule
Average & $ 2 $ & $ 2 $ & $ 1 $ \\
\bottomrule
\end{mytabular}

\bigskip

\begin{mytabular}{
  colspec = {| L{6em} | C{6em} C{6em} C{6em} |},
  row{1} = {font = \bfseries},
}
\toprule
Column & First & Second & Third \\
\midrule
First  & $ 3 $ & $ 5 $ & $ 2 $ \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third  & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $ \\
\midrule
Average & $ 2 $ & $ 2 $ & $ 1 $ \\
\bottomrule
\end{mytabular}

\end{document}

enter image description here

3
  • 1
    The question here is not so much about the rules (vertical and horizontal), but also about the spacing above/below the rules. Can tabularray manage that?
    – Werner
    Sep 9 at 22:37
  • 1
    Thanks. I will update my answer later.
    – L.J.R.
    Sep 9 at 22:39
  • 1
    I compared my result with that of the original poster. The vertical space is the same.
    – L.J.R.
    Sep 9 at 22:52
3

A bunch of alternatives using makecell, cellspace, nicematrix or tabularray:

\documentclass{article}

\newcommand{\PreserveBackslash}[1]{\let\temp=\\#1\let\\=\temp}
\newcolumntype{C}[1]{>{\PreserveBackslash\centering}p{#1}}
\newcolumntype{R}[1]{>{\PreserveBackslash\raggedleft}p{#1}}
\newcolumntype{L}[1]{>{\PreserveBackslash\raggedright}p{#1}}

\usepackage{makecell}
\setcellgapes{3pt}

\usepackage[column=0]{cellspace}
\setlength{\cellspacetoplimit}{3pt}
\setlength{\cellspacebottomlimit}{\cellspacetoplimit}

\usepackage{nicematrix}

\usepackage{tabularray}

\begin{document}

{
\makegapedcells
\begin{tabular}{| L{6em} | C{6em} C{6em} C{6em} |}
\hline
\textbf{Column} & \textbf{First} & \textbf{Second} & \textbf{Third} \\
\hline
First  & $ 3 $ & $ 5 $ & $ 2 $ \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third  & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $ \\
\hline
Average & $ 2 $ & $ 2 $ & $ 1 $ \\
\hline
\end{tabular}
}

\begin{tabular}{| 0{L{6em}} | 0{C{6em}} 0{C{6em}} 0{C{6em}} |}
\hline
\textbf{Column} & \textbf{First} & \textbf{Second} & \textbf{Third} \\
\hline
First  & $ 3 $ & $ 5 $ & $ 2 $ \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third  & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $ \\
\hline
Average & $ 2 $ & $ 2 $ & $ 1 $ \\
\hline
\end{tabular}

{
\NiceMatrixOptions{cell-space-limits = 3pt}
\begin{NiceTabular}{| L{6em} | C{6em} C{6em} C{6em} |}
\hline
\textbf{Column} & \textbf{First} & \textbf{Second} & \textbf{Third} \\
\hline
First  & $ 3 $ & $ 5 $ & $ 2 $ \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third  & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $ \\
\hline
Average & $ 2 $ & $ 2 $ & $ 1 $ \\
\hline
\end{NiceTabular}
}

\begin{tblr}{| Q[t,l,6em] | Q[t,c,6em] Q[t,c,6em] Q[t,c,6em] |}
\hline
\textbf{Column} & \textbf{First} & \textbf{Second} & \textbf{Third} \\
\hline
First  & $ 3 $ & $ 5 $ & $ 2 $ \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third  & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $ \\
\hline
Average & $ 2 $ & $ 2 $ & $ 1 $ \\
\hline
\end{tblr}
\end{document}
1
  • Thanks! I have similar questions as for the other answer. Thanks! Does this apply padding specifically to the cells around rules (as it should) or to all cells? Moreover, do you know how to turn this into a custom table environment, such that my tables can use the normal tabular/tabularx syntax?
    – danijar
    Sep 9 at 19:26
2

Something like this? I defined an environment which removes the vertical padding of the booktabs rules, and replaced it with \setcellgapes{…}\makegapedcells from malecell.

\documentclass{article}
\usepackage{tabularx, booktabs, makecell}
\newcommand{\PreserveBackslash}[1]{\let\temp=\\#1\let\\=\temp}
\newcolumntype{C}[1]{>{\PreserveBackslash\centering}p{#1}}
\newcolumntype{R}[1]{>{\PreserveBackslash\raggedleft}p{#1}}
\newcolumntype{L}[1]{>{\PreserveBackslash\raggedright}p{#1}}

% TODO: Define custom mytable environment here...
\newenvironment{mytable}[1][]{\table[#1]
\setlength{\aboverulesep}{0pt}
\setlength{\belowrulesep}{0pt}
\setcellgapes{4pt}\makegapedcells}%
{\endtable}

\begin{document}

\begin{mytable}[!h]
\begin{tabular}{!{\vrule width 0.08em}L{6em}!{\vrule width 0.06em} *{3}{C{6em}}!{\vrule width 0.08em}}
\toprule
\textbf{Column} & \textbf{First} & \textbf{Second} & \textbf{Third} \\
\midrule
First & $ 3 $ & $ 5 $ & $ 2 $ \\
Second & $ 1 $ & $ 0 $ & $ 0 $ \\
Third & $ 4 $ & $ 3 $ & $ 2 $ \\
Fourth & $ 0 $ & $ 0 $ & $ 0 $ \\
\midrule
Average & $ 2 $ & $ 2 $ & $ 1 $ \\
\bottomrule
\end{tabular}
\end{mytable}

\end{document} 

enter image description here

2
  • Thanks! Is \setcellgapes{4pt} applied around rules only or around all cells? In your example output, it looks as if it also adds white space between the rows that have no rule between them. Moreover, do you know how to apply the rule widths automatically, without having to specify them in the header of each individual table?
    – danijar
    Sep 9 at 19:23
  • It adds 4pt at the top and at the bottom of each cell. This value was chosen as an illustrating example. If you don't want it for all cells, but only for those between rules, you can use the \Gape command for selected cells, say \Gape[4pt]{\textbf{Column}} and similarly for ‘Average’.
    – Bernard
    Sep 9 at 19:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.