# How to shade text in different colors?

I need a single character in two colors. Figuring I could use the shadings library of TikZ, I followed the manual (section 23.4.1, the TikZ example):

\documentclass{article}

\usepackage{tikz}

\begin{document}

\node[text=transparent!0] {$4$};
(0,0) rectangle (2ex,2ex);}

\end{document}


However, the result is no good for two reasons:

1. The surrounding box is far too large; it's not possible to use the character in text of formulae.
2. Only the center part of the shading is visible in the character, rendering it almost invisible.

How can I make the shading apply only to the character, without any surrounding space?

If it's easier, I can also do without the shading but a hard change of colors, that is something like this (gimped):

The angle of the separation line is not that important.

Here is another suggestion:

\documentclass[varwidth,margin=5mm]{standalone}

\usepackage{tikz}

\node[text=transparent!0,inner xsep=0pt,outer xsep=0pt,#1] {#3};
\begin{tikzpicture}[baseline=(textnode.base)]
\node[inner sep=0pt,outer sep=0pt,#1](textnode){\phantom{#3}};
(textnode.south west) rectangle (textnode.north east);%
\end{tikzpicture}%
}

\begin{document}
\setlength\fboxsep{0pt}
\fbox{%
\fadingtext[scale=10]{top color=orange,bottom color=purple}{$4$}%
}
\end{document}


You can use this to color text:

Code:

\documentclass[varwidth,margin=5mm]{standalone}
\usepackage{tikz}
\node[text=transparent!0,inner xsep=0pt,outer xsep=0pt,#1] {#3};
\begin{tikzpicture}[baseline=(textnode.base)]
\node[inner sep=0pt,outer sep=0pt,#1](textnode){\phantom{#3}};
(textnode.south west) rectangle (textnode.north east);%
\end{tikzpicture}%
}
\usepackage{lipsum}
\begin{document}
\setlength\fboxsep{0pt}
\fbox{%
\fadingtext[scale=4]{top color=orange,bottom color=purple}{$4$}%
}

A short test with green and purple: \fadingtext{left color=green,right color=purple}{green to purple}

\end{document}


Here is an additional suggestion with a sharp border between the two colors:

Code:

\documentclass[margin=5mm,varwidth]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{lipsum}
\tikzset{
bctleft/.style={.},
text left/.style={bctleft/.append style={#1}},
bctright/.style={.},
text right/.style={bctright/.append style={#1}},
}
\newcommand\bicolortext[2][]{%
\tikz[baseline=(n.base),inner sep=0pt,outer xsep=0pt,#1]{
\node(n){\phantom{#2}};
\foreach \a/\c in {north west/bctleft,south east/bctright}{
\begin{scope}
\clip(n.south west)--(n.\a)--(n.north east)--cycle;
\node[\c]at(n){#2};
\end{scope}
}}}
\begin{document}
\tikzset{text left=orange,text right=purple}
\setlength\fboxsep{0pt}
\fbox{%
\bicolortext[scale=4,transform shape]{$4$}%
}

A short test with green and purple: \bicolortext[text left=green, text right=purple]{green to purple}

\noindent\bicolortext{\parbox[b]{\linewidth}{\strut\lipsum[1]}}
\end{document}


With TikZ version 3.0 you can also use the transparency group=knockout option. Then it is possible to shade diagonal. But AFAIK only Acrobat Reader shows the correct result, because only this viewer is able to handle transparencies.

Code:

\documentclass[varwidth,margin=5mm]{standalone}
\usepackage{tikz}
\begin{tikzpicture}[baseline=(textnode.base)]
\begin{scope}[transparency group=knockout]
\fill[white](textnode.south west)rectangle(textnode.north east);
\node[opacity=0,inner sep=0pt,outer xsep=0pt,#1]{#3};
\end{scope}
\end{tikzpicture}%
}
\usepackage{lipsum}
\begin{document}
\setlength\fboxsep{0pt}
\fbox{\fadingtext[scale=10]{top color=orange,bottom color=purple}{$4$}}

A short test with green and purple: \fadingtext{left color=green,right color=purple}{green to purple}

\end{document}

• I have trouble seeing how the first (relevant) part differs from my approach, aside from wrapping it in a nicer command. But, apparently, the specific combination of which seps to set to 0 and where to scale matters. Curious. – Raphael Jul 21 '14 at 16:27

Another solution exploiting the text rendering modes of the PDF specification to render the text as a clipping path:

\documentclass[border=5]{standalone}
\usepackage{tikz}
\setbox0=\hbox{{\special{pdf:literal 7 Tr }#2}}%
\tikz[baseline=0]\path [#1] \pgfextra{\rlap{\copy0}} (0,-\dp0) rectangle (\wd0,\ht0);%
}
\begin{document}
Some
text
\end{document}


Although it uses PDF specials, the nice thing about this approach is it is easy to extend it to use an arbitrary picture:

\documentclass[border=5]{standalone}
\usepackage{tikz,lipsum}
\newbox\textpicturebox
\tikzset{text picture/.style={%
path picture={%
\pgfmathsetlengthmacro\textpicturewidth{\wd\textpicturebox}%
\pgfmathsetlengthmacro\textpictureheight{\ht\textpicturebox+\dp\textpicturebox}%
\pgftransformshift{\pgfpointanchor{path picture bounding box}{center}}%
#1}}}%
\setbox\textpicturebox=\hbox{{\special{pdf:literal 7 Tr }#2}}%
\tikz[baseline=0]\path \pgfextra{\rlap{\copy\textpicturebox}} [#1] (0,-\dp\textpicturebox) rectangle (\wd\textpicturebox,\ht\textpicturebox);
}
\begin{document}
\tikzset{shift=(90:2)}
\fill [green!75!brown] (-0.25,0) rectangle (0.25,-7);
\fill [green!75!brown] (0,-7) [rotate=-45]  arc (270:-90:0.5 and 2);
\fill [green!75!brown] (0,-7) [rotate=45]  arc (270:-90:0.5 and 2);
\foreach \i [evaluate={\o=mod(\i/30,2)*100;}] in {0,30,...,330}
\fill [red!\o!pink]
(0,0) -- (\i:3) .. controls ++(\i:1cm) and ++(\i+30:1) .. (\i+30:3) -- cycle;
}]{\Large\bfseries\begin{minipage}{4in}\lipsum[1]\end{minipage}}
\end{document}


• Who wouldn't want a flower-shaped shading? – Raphael Jul 24 '14 at 17:58
• This solution is great. Just notice that middle color option must be placed after left color and right color. – Hansimov Aug 31 '18 at 2:23

Here is a solution with pstricks, and more precisely with pst-grad and pst-text. It is compilable with pdf LaTeX, and the box size can be changed with \psframebox[framesep=…]{…}:

\documentclass[pdf, x11names]{article}
\psset{framesep=2pt}
\begin{document}

Some text
\begin{tabular}{lll}
\psframebox[linecolor = Coral1!20]{%
\pscharpath[linestyle=none,%
& \psframebox[linecolor = Coral1!20]{%
\pscharpath[linestyle=none,%
& \psframebox[linecolor = Coral1!20]{%
\pscharpath[linestyle=none,%
\end{tabular}

\end{document}


• Do you compile this file using pdflatex directly or you need to go around dvi2pdf? – Dox Jul 21 '14 at 14:40
• Directly. You have to set --enable-write18 (MiKTeX) or --shell-escape (TeX Live, MacTeX) as a compiler option (it loads auto-pst-pdf). Or you may compile with XeLaTeX. Added: I modified my answer to have a tighter box. – Bernard Jul 21 '14 at 14:48

It is possible to create a more reasonable box by printing the character again and anchoring the shading at this node:

\fbox{
\begin{tikzpicture}[scale=10]
\node [text=white,inner sep=0pt,outer sep=0pt] (textnode) {$4$};