5

I have been successfully using xcolor and its \cellcolor command for a while, and produced beautiful results with it. However, I would like to create some more advanced background effects: color the cell with two colors:

Example of attempted solutions

The example above is produced using https://tex.stackexchange.com/a/263403/17312, but this approach falls apart for a number of reasons:

  1. Tikz's matrix command is not nearly as powerful as ordinary tabulars with the array package and others. I have some numeric data that I am happily aligning on the decimal point using dcolumn - I have no idea how I would do this is in a tikz matrix.
  2. I would like to emulate booktabs behaviour, but I just can't get it working. https://tex.stackexchange.com/a/21178/17312 suggests a workaround, but it doesn't work.
  3. The coloring falls apart if the width of the columns is not predefined: Example 2

    and it all falls apart.

  4. I have had a look through other questions; https://tex.stackexchange.com/a/346212/17312 and https://tex.stackexchange.com/a/81998/17312 manage to create one-colored bars dynamically; https://tex.stackexchange.com/a/148797/17312 combines tabularx and tikz in a promising approach, but I did not manage to adapt this to my purpose; Aligning tikz nodes to tabular cells? draws lines and manages to stick to a tabular environment - maybe a good starting point?

So ideally I would like to stick to a tabular environment, and be able to specify the cells' background content freely (for the point of this question I would be happy with a solution that gives me the diagonally separated effect as in the top left corner of the two examples), with a command such as \twocolor{blue}{purple}.

2

A more flexible background definition can be done by collecting from my answer to TikZ: Rectangle with diagonal fill (two colors) and Gonzalo's answer to Set table background hatched and shaded using tikz. There are some spacing issues, mostly (I think) because I'm not quite aware of the padding macros inside the tabular cells, specially with booktabs rules (toprule, \midrule,...), so it works better with \hline right now, but I'm sure it can be easily improved.

The column specifier is not overruled, but it needs to be specified explicitly. In the below MWE I use dcolumn but I recommend the use of siunitx instead, as done by Salim Bou.

MWE

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{tikzmark, calc}
% Makes a style for double color filling
\tikzset{
    double color fill/.code 2 args={
        \pgfdeclareverticalshading[%
            tikz@axis@top,tikz@axis@middle,tikz@axis@bottom%
        ]{diagonalfill}{100bp}{%
            color(0bp)=(tikz@axis@bottom);
            color(50bp)=(tikz@axis@bottom);
            color(50bp)=(tikz@axis@middle);
            color(50bp)=(tikz@axis@top);
            color(100bp)=(tikz@axis@top)
        }
        \tikzset{shade, left color=#1, right color=#2, shading=diagonalfill}
    }
}
% Code adapted from Gonzalo: https://tex.stackexchange.com/a/67096/81905
\newcommand\BGcell[4][0pt]{%
  \begin{tikzpicture}[overlay,remember picture]%
    \path[#4] ( $ (pic cs:#2) + (-.5\tabcolsep,1.9ex) $ ) rectangle ( $ (pic cs:#3) + (\tabcolsep,-#1*\baselineskip-.8ex) $ );
  \end{tikzpicture}%
}%
\newcounter{BGnum}
\setcounter{BGnum}{1}
\newcommand\cellBG[3]{
    \multicolumn{1}{
        !{\BGcell{startBG\arabic{BGnum}}{endBG\arabic{BGnum}}{%
                #1}
            \tikzmark{startBG\arabic{BGnum}}}
            #2
        !{\tikzmark{endBG\arabic{BGnum}}}}
        {#3} 
      \addtocounter{BGnum}{1}
}
% end of code from Gonzalo

\usepackage{dcolumn, array, booktabs}
\newcolumntype{.}{D{.}{.}{-1}}
\newcommand*{\tabhead}[1]{\multicolumn{1}{c}{#1}}

\begin{document}
  \tikzset{%
    diagonal fill/.style 2 args={%
        double color fill={#1}{#2},
        shading angle=45,
        opacity=0.8},
    other filling/.style={%
        shade,
        shading=myshade,
        shading angle=0,
        opacity=0.5}
   }
  % Other crazy filling options using shading
  \pgfdeclarehorizontalshading{myshade}{100bp}{%
      color(0bp)=(blue);
      color(25bp)=(blue);
      color(37.5bp)=(blue);
      color(37.5bp)=(brown);
      color(50bp)=(brown);
      color(50bp)=(green);
      color(62.5bp)=(green);
      color(62.5bp)=(purple);
      color(75bp)=(red);
      color(100bp)=(red)}

  \begin{tabular}{c.}
    \toprule
    \cellBG{double color fill={red}{blue}, shading angle=-45, opacity=0.5}{c}{Header 1} & \tabhead{Header 2}\\
    \midrule
    \cellBG{diagonal fill={yellow}{green}}{c}{Text} & \cellBG{other filling}{.}{1.2333}\\
    \cellBG{other filling}{c}{Text} & 154.622\\
    Text & 1.244\\
    Text & 11.3\\
    Text & 121.2\\
    \bottomrule
  \end{tabular}
\end{document}

This method relies on TikZ shadings, they're not so complicated to define and are very powerful. One thing to take into account when declaring a shading is that if you define it to be of 100bp it will automatically scale, and the visible part of the shading will be between 25bp and 75bp, that's why my Multi Color shading has blue from 0bp to 25bp, because that part is actually hidden. The key shading angle can be used to set the diagonal slant, other types of shading can be defined as well (check the manual for more info).

enter image description here

  • Very nice. This comes closest to what I want to achieve. Why does the content of each cell needs to be wrapped in another \multicolumn? – Karalga Jan 18 '17 at 12:36
  • Because if you look closely, inside the column specifier, in the \multicolumn there's a !{...} declaration which computes the mark from tikzmark. You could maybe create \newcolumntypes to compute the marks for every cell but only background selectively... – Guilherme Zanotelli Jan 18 '17 at 13:02
4

Based on @leoLiu solution to create cell with diagonal line. In the example I use suinitx rather then dcolumn to align numbers on decimal point.

\documentclass[11pt]{article}
\usepackage{array}
\usepackage{siunitx}
\usepackage{booktabs}
\usepackage{tikz}


\newcommand\diagfil[4]{%
  \multicolumn{1}{p{#1}}{\hskip-\tabcolsep
  $\vcenter{\begin{tikzpicture}[baseline=0,anchor=south west,inner sep=0pt,outer sep=0pt]
  \path[use as bounding box] (0,0) rectangle (#1+2\tabcolsep,\baselineskip);
  \node[minimum width={#1+2\tabcolsep},minimum height=\baselineskip+\extrarowheight+\belowrulesep+\aboverulesep,fill=#2] (box)at(0,-\aboverulesep) {};
  \fill [#3] (box.south west)--(box.north east)|- cycle;
  \node[anchor=center] at (box.center) {#4};
  \end{tikzpicture}}$\hskip-\tabcolsep}}

\begin{document}

\centering

\begin{tabular}{SSSSS}
\toprule
\diagfil{2cm}{blue}{purple}{Text} &&&&2.0\\
\midrule
  &  &  &  &3.03\\ 
15&12&18&50&4.5\\
15&12&18&50&4.54\\
\bottomrule
\end{tabular}
\end{document}

enter image description here

  • Interesting approach! However this overwrites the column definition for the cell - (e.g.) I would like to be able to get the decimal point alignment also in the cell with the background. – Karalga Jan 16 '17 at 15:45

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.