17

I'd like to highlight certain cells of my table. In particular, I'd like to set the border of these sells colored and thick. These cells should also have a background color.

Here's a minimal example of my table:

\documentclass{article}
\usepackage{array,colortbl,xcolor}

\begin{document} 

\begin{tabular}{p{1.4cm}p{2.55cm}p{2.55cm}p{2.55cm}p{2.55cm}}
\hline
\multicolumn{1}{c}{} & \multicolumn{2}{c}{\textbf{Football}} & \multicolumn{2}{c}{\textbf{Basketball}} \\\hline
\multicolumn{1}{c}{} & \multicolumn{1}{c}{\textbf{1. League}} & \multicolumn{1}{c}{\textbf{2. League}} & \multicolumn{1}{c}{\textbf{1. League}} & \multicolumn{1}{c}{\textbf{2. League}} \\ \hline
\textbf{Average} & 10000000000 & \cellcolor{lightgray}20000000000 & 30000000000 & 40000000000\\ \hline
\textbf{Total} & 50000000000 & 60000000000 & 70000000000 & \cellcolor{lightgray}80000000000\\ \hline

\end{tabular}
\end{document}

I tried to set the border of specific cells using a combination of multicolumn and hhline but failed miserably :-( (One of the problems was that the cell background partially covers the border).

I also tried tikz but failed to paint exactly on the cell's border, especially when a linebreak occurs.

Here's how it should look optimally:

enter image description here

Can someone please help me to get this working?

4 Answers 4

12

enter image description here

I have prevented the cell from becoming wider due to the border, but allowed it to grow vertically. If that isn't desired a bit more negative spacing is needed.

rather than use colortbl it is easier to grab the cell contents in a box (since you are doing that anyway for p columns) and using \fcolorbox.

\documentclass{article}
\usepackage{array,colortbl,xcolor}

\begin{document} 

\makeatletter
\def\highlight#1{%
\fboxrule2pt %
\hsize=\dimexpr\hsize-2\fboxrule-2\fboxsep\relax
#1%
\@endpbox\unskip\setbox0\lastbox\bgroup
\fboxrule2pt %
\fcolorbox{red}{lightgray}{\box0}\hfill}

\begin{tabular}{p{1.4cm}p{2.55cm}p{2.55cm}p{2.55cm}p{2.55cm}}
\hline
\multicolumn{1}{c}{} & \multicolumn{2}{c}{\textbf{Football}} & \multicolumn{2}{c}{\textbf{Basketball}} \\\hline
\multicolumn{1}{c}{} & \multicolumn{1}{c}{\textbf{1. League}} & \multicolumn{1}{c}{\textbf{2. League}} & \multicolumn{1}{c}{\textbf{1. League}} & \multicolumn{1}{c}{\textbf{2. League}} \\ \hline
\textbf{Average} & 10000000000 & \cellcolor{lightgray}20000000000 & 30000000000 & 40000000000\\ \hline
\textbf{Total} & 50000000000 & 60000000000 &
\highlight{70000000000}& \cellcolor{lightgray}80000000000\\ \hline

\end{tabular}
\end{document}
3
  • Thank you so much for this nice solution! I still have a minor request for improvement: Is it possible, that the red box takes the whole space of the cell, i.e. that it has contact with the left and right cell? In the current solution there is a small white space. Commented Aug 15, 2012 at 21:13
  • I think you are just seeing the tabcolsep space between columns in a tabular if you suppress that with p{2.55cm}@{}p{2.55cm} where the @{} suppresses all inter-column material, two adjacent \highlight entries touch when I try it. Commented Aug 15, 2012 at 21:25
  • How would you vertically fit the bordered fbox exactly in the cell? In your example, the bordered cells are higher than regular cells. Commented Feb 21, 2018 at 23:35
5

I provide a solution with TikZ and the now famous \tikzmark macro.

\documentclass{article}
\usepackage{xparse}
\usepackage{tikz}
\usetikzlibrary{calc}

% to change colors
\newcommand{\fillcol}{blue!20}
\newcommand{\bordercol}{blue}

\newcommand{\setfillcolor}[1]{\renewcommand{\fillcol}{#1}}
\newcommand{\setbordercolor}[1]{\renewcommand{\bordercol}{#1}}

%% code by Andrew Stacey 
% https://tex.stackexchange.com/questions/51582/background-coloring-with-overlay-specification-in-algorithm2e-beamer-package#51582

\makeatletter
\tikzset{%
     remember picture with id/.style={%
       remember picture,
       overlay,
       save picture id=#1,
     },
     save picture id/.code={%
       \edef\pgf@temp{#1}%
       \immediate\write\pgfutil@auxout{%
         \noexpand\savepointas{\pgf@temp}{\pgfpictureid}}%
     },
     if picture id/.code args={#1#2#3}{%
       \@ifundefined{save@pt@#1}{%
         \pgfkeysalso{#3}%
       }{
         \pgfkeysalso{#2}%
       }
     }
   }

   \def\savepointas#1#2{%
  \expandafter\gdef\csname save@pt@#1\endcsname{#2}%
}

\def\tmk@labeldef#1,#2\@nil{%
  \def\tmk@label{#1}%
  \def\tmk@def{#2}%
}

\tikzdeclarecoordinatesystem{pic}{%
  \pgfutil@in@,{#1}%
  \ifpgfutil@in@%
    \tmk@labeldef#1\@nil
  \else
    \tmk@labeldef#1,(0pt,0pt)\@nil
  \fi
  \@ifundefined{save@pt@\tmk@label}{%
    \tikz@scan@one@point\pgfutil@firstofone\tmk@def
  }{%
  \pgfsys@getposition{\csname save@pt@\tmk@label\endcsname}\save@orig@pic%
  \pgfsys@getposition{\pgfpictureid}\save@this@pic%
  \pgf@process{\pgfpointorigin\save@this@pic}%
  \pgf@xa=\pgf@x
  \pgf@ya=\pgf@y
  \pgf@process{\pgfpointorigin\save@orig@pic}%
  \advance\pgf@x by -\pgf@xa
  \advance\pgf@y by -\pgf@ya
  }%
}

\NewDocumentCommand{\tikzmarkin}{m D(){0.825,-0.10} D(){-0.175,0.27}}{%
      \tikz[remember picture,overlay]
      \draw[line width=1pt,rectangle,fill=\fillcol,draw=\bordercol]
      (pic cs:#1) ++(#2) rectangle (#3)
      ;}

\newcommand\tikzmarkend[2][]{%
\tikz[remember picture with id=#2] #1;}


\begin{document} 
\setfillcolor{lightgray}
\setbordercolor{red}
\begin{tabular}{p{1.4cm}p{2.55cm}p{2.55cm}p{2.55cm}p{2.55cm}}
\hline
\multicolumn{1}{c}{} & \multicolumn{2}{c}{\textbf{Football}} & \multicolumn{2}{c}{\textbf{Basketball}} \\\hline
\multicolumn{1}{c}{} & \multicolumn{1}{c}{\textbf{1. League}} & \multicolumn{1}{c}{\textbf{2. League}} & \multicolumn{1}{c}{\textbf{1. League}} & \multicolumn{1}{c}{\textbf{2. League}} \\ \hline
\textbf{Average} & \tikzmarkin{d}(0.1,-0.1)(-0.1,0.27)10000000000\tikzmarkend{d} & \tikzmarkin{b}20000000000\tikzmarkend{b} & 30000000000 & 40000000000\\ \hline
\textbf{Total} & 50000000000 & 60000000000 & \tikzmarkin{c}70000000000\tikzmarkend{c} & \tikzmarkin{a}80000000000\tikzmarkend{a}\\ \hline

\end{tabular}
\end{document}

The default setting allows to get the so called optimal look, but it is also possible to shorten the highlighting box. This is why the \tikzmark version adopted is taken from Issues and potentiality of the tikzmark macro: dynamic box adaptation and uses extendible markers. An example is given in the above code:

\tikzmarkin{d}(0.1,-0.1)(-0.1,0.27)10000000000\tikzmarkend{d}

where (0.1,-0.1) represent the end shift marker and (-0.1,0.27) the in shift marker.

The solution leads to:

enter image description here

This approach requires the document to be compiled twice and even allows to get something like:

enter image description here

\begin{document} 
\setfillcolor{lightgray}
\setbordercolor{red}
\begin{tabular}{p{1.4cm}p{2.55cm}p{2.55cm}p{2.55cm}p{2.55cm}}
\hline
\multicolumn{1}{c}{} & \multicolumn{2}{c}{\textbf{Football}} & \multicolumn{2}{c}{\textbf{Basketball}} \\\hline
\multicolumn{1}{c}{} & \multicolumn{1}{c}{\textbf{1. League}} & \multicolumn{1}{c}{\textbf{2. League}} & \multicolumn{1}{c}{\textbf{1. League}} & \multicolumn{1}{c}{\textbf{2. League}} \\ \hline
\textbf{Average} & \tikzmarkin{d}(0.1,-0.1)(-0.1,0.27)10000000000 & \tikzmarkin{b}20000000000\tikzmarkend{b} & 30000000000 & 40000000000\\ \hline
\textbf{Total} & 50000000000\tikzmarkend{d} & 60000000000 & \tikzmarkin{c}70000000000\tikzmarkend{c} & \tikzmarkin{a}80000000000\tikzmarkend{a}\\ \hline
\end{tabular}
\end{document}
2
  • Looks complicated for beginners, but works like a charm. Especially the boxes across multiple cells are neat.
    – Klaster
    Commented Sep 22, 2015 at 14:25
  • @Klaster: Glad it helps. Yes, I think this solution can give a lot of flexibility. Commented Sep 22, 2015 at 14:27
2

I couldn't run David Carlisle's the last solution, perhaps due to changes in the array package (using v2.4l).

I'm not fluent in TeX to correct the definition of highlight, so I wrote a new command highlighti which seems to get the same result.

I also changed the column specs from p to w to have better number alignment, and added a stretch to the rows to make more room for the edges.

\documentclass{article}
\usepackage{array,colortbl,xcolor}

\begin{document} 

%   \makeatletter
%   \def\highlight#1{%
%       \fboxrule2pt %
%       \hsize=\dimexpr\hsize-2\fboxrule-2\fboxsep\relax
%       #1%
%       \@endpbox\unskip\setbox0\lastbox\bgroup
%       \fboxrule2pt %
%       \fcolorbox{red}{lightgray}{\box0}\hfill}

\newcommand{\highlighti}[2]{%
    \setlength{\fboxrule}{2pt}%
    \fcolorbox{#1}{lightgray}{#2}}

    \renewcommand{\arraystretch}{1.7} %make room for borders
    
%\begin{tabular}{p{1.4cm}p{2.55cm}p{2.55cm}w{c}{2.55cm}p{2.55cm}}
\begin{tabular}{p{1.4cm}w{c}{2.55cm}w{c}{2.55cm}w{c}{2.55cm}w{c}{2.55cm}}   % changed for better alignment
    \hline
    \multicolumn{1}{c}{} & \multicolumn{2}{c}{\textbf{Football}} & \multicolumn{2}{c}{\textbf{Basketball}} \\
    \hline
    \multicolumn{1}{c}{} & \multicolumn{1}{c}{\textbf{1. League}} & \multicolumn{1}{c}{\textbf{2. League}} & \multicolumn{1}{c}{\textbf{1. League}} & \multicolumn{1}{c}{\textbf{2. League}} \\
     \hline
    \textbf{Average} & 10000000000 & \highlighti{white}{20000000000} & 30000000000 & \highlighti{white}{40000000000}\\ 
    \hline
    \textbf{Total} & 50000000000 & 60000000000 &
    \highlighti{red}{70000000000}
     & \highlighti{white}{80000000000}\\
     \hline
\end{tabular}

\end{document}

enter image description here

2

You can do that with {NiceTabular} of nicematrix.

\documentclass{article}
\usepackage{xcolor}
\usepackage{nicematrix}
\usepackage{tikz}

\begin{document} 

\begin{NiceTabular}{p{1.4cm}p{2.55cm}p{2.55cm}p{2.55cm}p{2.55cm}}[hlines]
& \Block{1-2}{\textbf{Football}} && \Block{1-2}{\textbf{Basketball}} \\
& \Block{}{\textbf{1. League}} & \Block{}{\textbf{2. League}} & \Block{}{\textbf{1. League}} & \Block{}{\textbf{2. League}} \\ 
\textbf{Average} & 10000000000 &\Block[l,fill=lightgray,draw=red,line-width=1.2pt]{}{20000000000} & 30000000000 & 40000000000\\ 
\textbf{Total} & 50000000000 & 60000000000 & 70000000000 &\Block[l,fill=lightgray,draw=red,line-width=1.2pt]{}{80000000000}\\ 
\end{NiceTabular}
\end{document}

Ouput of the first code

If you want the red lines completely inside the cells, it's also possible (≥ 6.24):

\documentclass{article}
\usepackage{nicematrix,tikz}

\begin{document} 

\newcommand{\MyBlock}{\Block[l,tikz={offset=0.6pt,fill=lightgray,draw=red,line width=1.2pt}]}

\begin{NiceTabular}{p{1.4cm}p{2.55cm}p{2.55cm}p{2.55cm}p{2.55cm}}[hlines,color-inside]
& \Block{1-2}{\textbf{Football}} && \Block{1-2}{\textbf{Basketball}} \\
& \Block{}{\textbf{1. League}} & \Block{}{\textbf{2. League}} & \Block{}{\textbf{1. League}} & \Block{}{\textbf{2. League}} \\ 
\textbf{Average} & 10000000000 & \MyBlock{}{20000000000} & 30000000000 & 40000000000\\ 
\textbf{Total} & 50000000000 & 60000000000 & 70000000000 &\MyBlock{}{80000000000}\\ 
\end{NiceTabular}
\end{document}

Output of the second code

You must log in to answer this question.

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