[Tex/LaTex] TikZ: shade also the border of a node

nodesshadingtikz-pgftikz-styles

I would like to shade a node and the border of the node.

The following code works but I don't like it very much that I have to draw something after the node on the background layer. I would prefer a solution which can be used in a style and used on the node directly. Has someone a good idea?

\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\usepackage{tikz}
\usetikzlibrary{backgrounds}
\usetikzlibrary{calc}

\tikzset{
 shrink inner sep/.code={
   \pgfkeysgetvalue{/pgf/inner xsep}{\currentinnerxsep}
   \pgfkeysgetvalue{/pgf/inner ysep}{\currentinnerysep}
   \pgfkeyssetvalue{/pgf/inner xsep}{\currentinnerxsep - 0.5\pgflinewidth}
   \pgfkeyssetvalue{/pgf/inner ysep}{\currentinnerysep - 0.5\pgflinewidth}
   }}
\begin{document}
\begin{tikzpicture}
\draw (0,0) node[rectangle,
      rounded corners,
      shading=axis,
      thick,
      outer sep=0pt,
      shrink inner sep,
      left color=red!50!white,
      right color=green!50!white
       ](A){abcabc abc};
 \begin{scope}[on background layer]
 \shade[rectangle,
        left color = red,
        right color= green,
        thick,
        rounded corners=4pt+\pgflinewidth]
       ($(A.south west)+(-\pgflinewidth,-\pgflinewidth)$) rectangle
       ($(A.north east)+(\pgflinewidth,\pgflinewidth)$)
        ;
\end{scope};
\end{tikzpicture}

\begin{tikzpicture}
\draw (0,0) node[rectangle,
       rounded corners,
       fill=red!50!white,
       draw=red,
       thick
       ](A){abcabc abc};
\end{tikzpicture}      

\begin{tikzpicture}
\draw (0,0) node[rectangle,
       rounded corners,
       shading=axis,
       left color=red!50!white,
       right color=green!50!white,
       draw=red,
       thick
       ](A){abcabc abc};
\end{tikzpicture}       
\end{document}

enter image description here

Best Answer

This may be a possible approach; two styles have been defined:

  • horizontal shaded border which receives as arguments the left and right color: horizontal shaded border=red and green
  • vertical shaded border which receives as arguments the top and bottom color: vertical shaded border=blue and orange

The code:

\documentclass[tikz,border=10pt,png]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\tikzset{
 shrink inner sep/.code={
   \pgfkeysgetvalue{/pgf/inner xsep}{\currentinnerxsep}
   \pgfkeysgetvalue{/pgf/inner ysep}{\currentinnerysep}
   \pgfkeyssetvalue{/pgf/inner xsep}{\currentinnerxsep - 0.5\pgflinewidth}
   \pgfkeyssetvalue{/pgf/inner ysep}{\currentinnerysep - 0.5\pgflinewidth}
   }
}

\tikzset{horizontal shaded border/.style args={#1 and #2}{
    append after command={
       \pgfextra{%                 
          \begin{pgfinterruptpath}
                \path[rounded corners,left color=#1,right color=#2]
                ($(\tikzlastnode.south west)+(-\pgflinewidth,-\pgflinewidth)$) 
                rectangle
                ($(\tikzlastnode.north east)+(\pgflinewidth,\pgflinewidth)$);        
           \end{pgfinterruptpath}
        } 
    }
  },
  vertical shaded border/.style args={#1 and #2}{
    append after command={
       \pgfextra{%                 
          \begin{pgfinterruptpath}
                \path[rounded corners,top color=#1,bottom color=#2]
                ($(\tikzlastnode.south west)+(-\pgflinewidth,-\pgflinewidth)$) 
                rectangle
                ($(\tikzlastnode.north east)+(\pgflinewidth,\pgflinewidth)$);        
           \end{pgfinterruptpath}
        } 
    }
  }
}
\begin{tikzpicture}
\draw (0,0) node[rectangle,
      rounded corners,
      thick,
      outer sep=0pt,
      shrink inner sep,
      left color=red!50!white,
      right color=green!50!white,
      horizontal shaded border=red and green
      ](A){abcabc abc};
\draw (2.5,0) node[rectangle,
      rounded corners,
      thick,
      outer sep=0pt,
      shrink inner sep,
      top color=cyan!50,
      bottom color=orange!50,
      vertical shaded border=blue and orange
      ](A){abcabc abc};
\end{tikzpicture}
\end{document}

The result:

enter image description here

Notes on the code

The border is drawn after the node by means of append after command; to access the node's anchors, the macro \tikzlastnode is of help: things are very similar to How to modify nodes in TikZ to automatically add a line on their top?