Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm trying to draw a path between nodes belonging to nested tikzpictures that are not in a direct parent-child relationship. The code looks like this:

\begin{tikzpicture}

    %Container 1
    \node [draw] at (0,0) (container1) {
        \begin{tikzpicture}
            \node at (0,0) (container1label) {Node 1};
            \node [draw,below=0.4 of container1label] (child1) {Node 1's Child};
        \end{tikzpicture}
    };

    %Container 2
    \node [draw] at (6,0) (container2) {
        \begin{tikzpicture}
            \node at (0,0) (container2label) {Node 2};
            \node [draw,below=0.4 of container2label] (child2) {Node 2's Child};
        \end{tikzpicture}
    };

    %Arrow, it should have been '\path (child1) edge[<->] (child2);' but it's not possible
    \draw [<->] (2.17,1.65) to [out=0,in=180](6.1,1.9);

\end{tikzpicture}

It makes sense that this is not possible but that means I'm going wrong somewhere, probably when nesting tikzpictures in the first place. I absolutely must have nodes visually within one another, but not necessarily with nested tikzpictures if there is another way. What is the correct way to achieve this?

share|improve this question
    
Welcome to TeX.SX! I would suggest to avoid using nested tikzpictures. Instead, you might be interested in pics, a new feature of version 3.0.0 of TikZ. An example of the latter can be found in How can I draw a TikZ element multiple times against a shaded background? –  Claudio Fiandrino Jul 4 at 8:03

3 Answers 3

Here you have three different ways of drawing and connecting nested nodes without using nested tikzpictures.

The first one uses fit library to draw a fitting node which covers child and label nodes. The fitting node is the container. As the container is drawn after other nodes, if you want to fill it, the node has to be drawn on background layer.

    %Container 1
    \node at (0,0) (container1label) {Node 1};
    \node [draw,below=0.4 of container1label] (child1) {Node 1's Child};
    \node[fit=(container1label) (child1),draw] (container1) {};

The second one uses a matrix node as container.

container/.style={matrix, draw, row sep=4mm}

    \node[container] (container1) {
        \node (container1label) {Node 1}; \\
        \node [draw] (child1) {Node 1's Child}; \\
    };

In this case, there is no need to use background library if you want to apply special styles to matrix node.

The last one uses pics. A pic allows to draw complex figures (not only nodes) and replicate them without using nested tikzpictures

[pics/container/.style 2 args={
        code={
            \node (-clabel) {#1};
            \node[draw, below=0.4 of -clabel] (-cchild) {#2};
        },
        background code={
            \node[fit=(-clabel) (-cchild),draw,pic actions] (-ccont) {};
        }}]

This pic has two arguments which are label and child text. I've used first solution, two nodes and a fitting one although similar results can be obtained with matrix solution.

All three solutions provide next graphic: enter image description here

Please, look at complete code to understand how to use node labels in pic solution:

\documentclass[tikz,border=3mm]{standalone}

\usetikzlibrary{fit,positioning,backgrounds}

\begin{document}

\begin{tikzpicture}
    %Container 1
    \node at (0,0) (container1label) {Node 1};
    \node [draw,below=0.4 of container1label] (child1) {Node 1's Child};
    \node[fit=(container1label) (child1),draw] (container1) {};

    %Container 2
    \node at (6,0) (container2label) {Node 2};
    \node [draw,below=0.4 of container2label] (child2) {Node 2's Child};
    \begin{scope}[on background layer]
        \node[fit=(container2label) (child2),draw,fill=red!30] (container2) {};
    \end{scope}

    \path (child1) edge[<->] (child2);
\end{tikzpicture}

\begin{tikzpicture}[container/.style={matrix, draw, row sep=4mm}] 
    %Container 1
    \node[container] (container1) {
        \node (container1label) {Node 1}; \\
        \node [draw] (child1) {Node 1's Child}; \\
    };

    %Container 2
    \node[container,fill=red!30] at (6,0) (container2) {
        \node (container2label) {Node 2}; \\
        \node [draw] (child2) {Node 2's Child}; \\
    };

    \path (child1) edge[<->] (child2);
\end{tikzpicture}

\begin{tikzpicture}[pics/container/.style 2 args={
        code={
            \node (-clabel) {#1};
            \node[draw, below=0.4 of -clabel] (-cchild) {#2};
        },
        background code={
            \node[fit=(-clabel) (-cchild),draw,pic actions] (-ccont) {};
        }}]

    \pic (c1) {container={Node 1}{Node 1's Child}};

    \pic[fill=red!30] (c2) at (6,0)  {container={Node 2}{Node 2's Child}};

    \path (c1-cchild) edge[<->] (c2-cchild);
\end{tikzpicture}
\end{document}
share|improve this answer

I finally managed to find a solution via the fit library and PGF layers:

\usetikzlibrary{fit}

\pgfdeclarelayer{parentlayer}
\pgfdeclarelayer{childlayer} 
\pgfdeclarelayer{arrowlayer} 
% Can add more layers if needed
\pgfsetlayers{parentlayer,childlayer,arrowlayer}
\begin{tikzpicture}

    \begin{pgfonlayer}{childlayer}

        \node at (0,0) (container1label) {Node 1};
        \node [draw,fill=orange,fill opacity=0.5,text opacity=1,below=0.4 of container1label] (child1) {Node 1's Child};

        \node at (4,2) (container2label) {Node 2};
        \node [draw,fill=orange,fill opacity=0.5,text opacity=1,below=0.4 of container2label] (child2) {Node 2's Child};

    \end{pgfonlayer}

    \begin{pgfonlayer}{parentlayer}

        \node [draw,fill=cyan,fill opacity=0.3,fit=(container1label) (child1)] (container1) {};
        \node [draw,fill=cyan,fill opacity=0.3,fit=(container2label) (child2)] (container2) {};

    \end{pgfonlayer}

    \begin{pgfonlayer}{arrowlayer}

        \draw [<->,color=red] (child1) to [out=0,in=180](child2);

    \end{pgfonlayer}

\end{tikzpicture}

enter image description here

It's not pretty in terms of nesting logically nested parts of the diagram. But it requires no manual fiddling, can nest as many layers as needed and preserves the depth relationship, i.e draws children over parents.

share|improve this answer

This is a nested tikzpicture approach. The two nodes are wrapped in a tikzpicture environment with remember picture and overlay options. Relative distance (via positioning library) is used to place the Node 1 and Node 2.

enter image description here

Code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,positioning,fit}
\begin{document}
\begin{tikzpicture}[remember picture,overlay]

%Container 1
\node (container1) {
\begin{tikzpicture}
\node at (0,0) (container1label) {Node 1};
\node [draw,below=0.4 of container1label] (child1) {Node 1's Child};
\node[draw,fit=(container1label)(child1)](containerA){};
\end{tikzpicture}
};

%Container 2
\node [right= 6cm of container1]
 (container2) {
\begin{tikzpicture}
\node at (0,0) (container2label) {Node 2};
\node [draw,below=0.4 of container2label] (child2) {Node 2's Child};
\node[draw,fit=(container2label)(child2)](containerB){};
\end{tikzpicture}
};
%Arrow, it should have been '\path (child1) edge[<->] (child2);' but it's not possible
\draw [<->] (child1) to [out=0,in=180](child2);
\end{tikzpicture}
\end{document}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.