# Gradient color in one cell of a table

I'm trying to create a tabular and I'm facing the following small issue.

I would like to make the background of one cell a gradient color. Is it easy to do that in LaTeX? And if so, how to do it?

-
To mark that the question is not solved just don't accept an answer. If after some time you still don't have a good working solution, you can offer a bounty on your question an have it pushed to the "featured" questions and thus you have a high chance of getting a good answer. (tex.stackexchange.com/?tab=featured) You can always comment any answer on what is missing or what could be improved and you can also edit your question to provide more detail. –  topskip Jun 10 '12 at 15:31

Here's one option using the improved version of \tikzmark exposed by Andrew Stacey in his answer to tikzmark to have different behaviour if first run (and mark locations not yet available). The idea is to use \multicolumn and the !{...} syntax from the array package to place the marks at the beginning and at the end of the cell; then \shade (from the TikZ package) was used to place the shade.

A little example showing some shading effects (one of them using the shadings library) when having various cells associated to the different column types (l,c, p{<length>} and merged cells):

\documentclass[10pt]{article}
\usepackage[margin=2cm]{geometry} % just for the example
\usepackage[frenchb]{babel}
\usepackage[table]{xcolor}
\usepackage{array}
\usepackage{tikz}
\usepackage{lipsum}

% Andrew Stacey's code from
% http://tex.stackexchange.com/a/50054/3954
\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}%
}%
}
\newcommand\tikzmark[2][]{%
\tikz[remember picture with id=#2] {#1;}}
\makeatother
% end of Andrew's code

\begin{tikzpicture}[overlay,remember picture]%
\shade[#4] ( $(pic cs:#2) + (0pt,2ex)$ ) rectangle ( $(pic cs:#3) + (0pt,-#1*\baselineskip-.8ex)$ );
\end{tikzpicture}%
}%

\begin{document}

left color=red!20,right color=green!20}
top color=green!20,bottom color=red!20}
left color=blue!20,right color=green!20}

\begin{tabular}{| l | p{6cm} | c |}
\hline
Uncolored cell
& \multicolumn{1}{!{\tikzmark{start1}} p{6cm} !{\vrule\tikzmark{end1}}}{\lipsum*[2]}
& Uncolored cell \\
\hline
\multicolumn{1}{!{\vrule\tikzmark{start2}} l !{\vrule\tikzmark{end2}}}{Another colored cell}
& Another uncolored cell & Another uncolored cell \\
\hline
Uncolored cell
& \lipsum[4]
& \multicolumn{1}{!{\tikzmark{start3}} c !{\vrule\tikzmark{end3}}}{Another colored cell}
\\
\hline
\multicolumn{2}{!{\vrule\tikzmark{start4}} c !{\vrule\tikzmark{end4}}}{Another merged colored cell}
& Uncolored cell \\
\hline
\end{tabular}

\end{document}


### A brief explanation on how to use the code

For each cell that will receive the shading you need to do the following:

1. Use \multicolumn{<number of columns>}{<format specification>}{<text>} specifying the second argument in the form

!{\tikzmark{<name1>}} <format> !{tikzmark{<name2>}}


where <name1> and <name2> can be quite arbitrary strings not previously used; I suggest using something like start<number>, end<number>, but you can use any other strings (valid for naming nodes in TikZ). If you need to add vertical rules to the cell, you must use \vrule inside !{...}; for example, to have vertical rules on both sides of the cell you can say

!{\vrule\tikzmark{<name1>}} <format> !{\vrule\tikzmark{<name2>}}

2. Use the \ShadeCell command in the following way:

\ShadeCell{<name1>}{<name2>}{<shade specification>}


where <name1> and <name2> are the strings you used in the previous step, and <shade specification> is a valid shade according to TikZ syntax. If the contents of the cell spans more than one line (when using a p{<length>} columns, for example), then you can use the optional argument of \ShadeCell with the proper value to make the shade cover the cell vertically; for example; if the text of the cell spans 5 lines then you need to use something like

\ShadeCell[4]{<name1>}{<name2>}{<shade specification>}


(The optional argument is the number n-1, where n is the number of lines that the text spans).

-
That's a cool application for tikzmark, but somehow my sense of proportionality is violated ;-) –  Stephan Lehmke Jun 10 '12 at 4:46
Thank you very much, that's indeed what I want. I don't really understand the 'first run' thing, so I'll let it go for now, I'm sure it will come to me when I actually compile it. For I still have a major problem: using the code you provided, I get two errors, the first one being: file 'pgflibrarytikzcalc.code.tex' not found. –  jlo17 Jun 10 '12 at 11:59
@jlo17 if the calc library is missing, then you have an outdated version of PGF. The current official version is 2.10. You can find out your version processing the following document: \documentclass{article} \usepackage{tikz} \begin{document} \pgfversion \end{document}. If your version is older, update your system. –  Gonzalo Medina Jun 10 '12 at 14:06
Okay, it took me all day, but I finally updated it. It now works. However, I found out there's an incompatibility with \usepackage[french]{babel} (just adding it in the code above). How can I get around that ? I also have two other problems: 1. I just found out, now that I can test it, that this also modifies the color of the text, which is something I want to avoid (I just want the background to change, not the text). Similarly, the color of the \hline underneath is also modified against my will. And my second problem is that if I change c to |c| in the multicolumn, the | aren't aligned. –  jlo17 Jun 10 '12 at 21:32
@jlo17 Please. those are a lot of new questions to answer in comments; accepting an answer to this question and opening a follow-up question would be better. 1. With the french option for babel you need to use \newcommand\tikzmark[1]{% \tikz[overlay,remember picture,baseline] { \node [anchor=base] (#1) {}; }} (notice the extra pair of braces) in the first code (since the french option makes ; active). –  Gonzalo Medina Jun 10 '12 at 21:48

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}

\begin{document}

\begin{tikzpicture}

\matrix (A) [matrix of nodes,
row 2 column 2/.style={ nodes = { top color=blue!20, bottom color=red!20 }}]
{
A & B & C \\
D & E & F \\
G & H & I \\
};
\end{tikzpicture}

\end{document}


This will produce

Added: If you need the full power of tabular, you're better off with Gonzalo's solution, especially since it looks much cleaner now. It is however possible to emulate at least some of the things you're asking for. Here's an updated example with fake l, r and c columns. (With manually set widths. It's probably possible to get automatic widths with some more work.) I also added a few lines and an ugly multicol hack.

Of course, once you start to add more and more, you soon end up with code that's at least as complicated as Gonzalo's.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix,calc}

\begin{document}

\begin{tikzpicture}
\matrix (A) [matrix of nodes, nodes in empty cells,
text height=9pt, text depth = 1pt,
row 3 column 1/.style={
nodes = { top color=green!20, bottom color=red!20 }},
row 2 column 2/.style={
nodes = { left color=blue!20, right color=red!20 }},
row 1 column 3/.style={
nodes = { top color=blue!20, bottom color=red!20 }},
column 1/.style={ text width=15mm, align=left },
column 2/.style={ text width=15mm, align=right },
column 3/.style={ minimum width=20mm} % centered!
]
{
Lorem & ipsum & dolor \\
sit & amet & consectetur \\
};
% Draw some lines
\draw (A-1-1.north east) -- (A-3-1.south east);
\draw[thick, dotted] (A-2-2.south west) -- (A-2-3.south east) -- (A-1-3.north east);
% Faked multicolumn
\node[text height=9pt,text depth=1pt] at ($(A-3-2)!0.50!(A-3-3)$) { Multicol text here };
\end{tikzpicture}

\end{document}


-
That seems interesting. But how do I adapt this to a tabular ? –  jlo17 Jun 10 '12 at 21:33
The updated solution seems very interesting, and it's much easier to read and to maintain than the other answer above whose code is quite unreadable. I would much rather have this solution. But I would rather have a real tabular, rather than an emulated one. Otherwise it might get difficult to adjust sizes automatically, or span a content over multiple columns/rows, or add vertical/horizontal lines, or any other advanced tabular manipulation that I know how to do, but wouldn't know how to do with a matrix (unless there's a solution for each of the issues described). –  jlo17 Jun 10 '12 at 22:55
@jlo17 I added a bit of the functionality you're asking for. But if you really need the full power of tabular, you're probably better off with Gonzalo's solution. –  mrf Jun 11 '12 at 12:12