2

I have the following problem: I would like to put a commutative diagram realised with tikzcd in a node in a tikzpicture. I made several attempts but when I try to insert diagrams in nodepart I always have problems:

  • in the second I lose the vertical alignment of the text with respect to the arrows,

  • in the third I have also the problem with colours

Here my code

\documentclass{amsart}
\usepackage{tikz}
\usepackage{tikz-cd}
\usetikzlibrary{arrows,patterns,decorations.markings,shapes.geometric,positioning,shapes.geometric,backgrounds,patterns,shadows,calc,shapes.multipart}
\begin{document}
\begin{tikzpicture}
    \tikzset{
    nodeoformula2/.style={rectangle,rounded corners=0.2cm,drop shadow={shadow xshift=1mm, shadow yshift=-1mm,opacity=1},draw=black, top color=white, bottom color=white,ultra thick, inner sep=4mm, text centered},
    nodepoint/.style={circle,draw=gray,fill=gray,inner sep=0.8mm}
}
\tikzset{
nodeoformula3/.style={rectangle split, rectangle split parts=2, 
      rounded corners=0.2cm,drop shadow={shadow xshift=1mm, shadow yshift=-1mm,opacity=1},draw=black, top color=white, bottom color=white, ultra thick, rectangle split part align={center,center},},
}
\tikzset{
    nodeoformula4/.style = {
        rectangle split,
        rectangle split parts=2,
        rectangle split part fill={#1}, 
        draw, rounded corners, text width=7cm,
        align=center, text=black,ultra thick,}, 
}
%------------------------------------------------   
\node[nodeoformula2] (B) at (0, 4) { 
    \begin{tikzcd}[font=\large, row sep=2.5em]
    A  \arrow[r,"T",line width=0.7pt] \arrow[d,"\Psi_T^*"',line width=0.7pt]&B \\
    C  \arrow[r,"F"',line width=0.7pt] &D \arrow[u,"\Psi_T"',line width=0.7pt]
    \end{tikzcd}
};
    \node[nodeoformula3] (B) at (0, 0) {  AAA   \nodepart{two} 
\begin{tikzcd}[font=\large, row sep=2.5em] 
A  \arrow[r,"T",line width=0.7pt] \arrow[d,"\Psi_T^*"',line width=0.7pt]& B\\
C  \arrow[r,"F"',line width=0.7pt] &D \arrow[u,"\Psi_T"',line width=0.7pt]
\end{tikzcd}
};
  \node[nodeoformula4={red!75!black,red!5!white}] (B) at (0, -4) {  AAA     \nodepart{two} 
\begin{tikzcd}[font=\large, row sep=2.5em] 
A  \arrow[r,"T",line width=0.7pt] \arrow[d,"\Psi_T^*"',line width=0.7pt]& B\\
C  \arrow[r,"F"',line width=0.7pt] &D \arrow[u,"\Psi_T"',line width=0.7pt]
\end{tikzcd}
};
 \end{tikzpicture}
 \end{document}
  • 1
    Welcome to TeX.SE! Your code has error(s). In general nesting tikz (tikz-cd˙`) images in nodes is not good idea, it only leads to problems :-( – Zarko Jan 20 at 11:55
3

The other answers state correctly that one should not nest tikzpictures. This means one should not nest them, no matter what. Rather, one is to use \saveboxes, which really save the day, also here.

\documentclass{amsart}
\usepackage{tikz}
\usetikzlibrary{backgrounds,cd,positioning,shadows,shapes.multipart}
\newsavebox\mycd
\begin{lrbox}{\mycd}
\begin{tikzcd}[font=\large, row sep=2.5em]
    A  \arrow[r,"T",line width=0.7pt] \arrow[d,"\Psi_T^*"',line width=0.7pt]&B \\
    C  \arrow[r,"F"',line width=0.7pt] &D \arrow[u,"\Psi_T"',line width=0.7pt]
\end{tikzcd}
\end{lrbox}
% https://tex.stackexchange.com/a/47009
\tikzset{on layer/.code={
    \pgfonlayer{#1}\begingroup
    \aftergroup\endpgfonlayer
    \aftergroup\endgroup
  }}

\begin{document}
\begin{tikzpicture}[nodeformula/.style={rectangle,rounded corners=0.2cm,
    drop shadow={shadow xshift=1mm, shadow yshift=-1mm,opacity=1,
    on layer=background},
    draw=black,inner sep=2mm,ultra thick, text centered},
    nodepoint/.style={circle,draw=gray,fill=gray,inner sep=0.8mm},
    nodeoformula2/.style={nodeformula,fill=white,
        % top color=white, bottom color=white %<-as of now no effect
        },
    nodeoformula3/.style={nodeformula,fill=white,rectangle split, rectangle split parts=2,
        rectangle split part align={center,center}, 
        % top color=white, bottom color=white %<-as of now no effect
         },
    nodeoformula4/.style={nodeformula,%top color=white, bottom color=white,
        rectangle split,
        rectangle split parts=2,
        rectangle split part fill={#1}, 
        }]
  \node[nodeoformula2] (B2) {\usebox\mycd};
  \node[nodeoformula3,below=of B2] (B3) {  AAA   \nodepart{two} 
      \usebox\mycd};
  \node[nodeoformula4={red!75!black,red!5!white},below=of B3] (B4)
      {  AAA     \nodepart{two} 
      \usebox\mycd};
\end{tikzpicture}
\end{document}

enter image description here

P.S. Using a path inside \pgfextra is equally bad as nesting tikzpictures. The "shadow on background" problem has this very simple solution.

ADDENDUM: Your second diagram. This is one of the cases in which you need to put the lrbox inside the document.

\documentclass{amsart}
\usepackage{tikz}
\usepackage{mathrsfs}
\usepackage{mathtools}
\usetikzlibrary{backgrounds,cd,positioning,shadows,shapes.multipart}
\newsavebox\mycd
% https://tex.stackexchange.com/a/47009
\tikzset{on layer/.code={
    \pgfonlayer{#1}\begingroup
    \aftergroup\endpgfonlayer
    \aftergroup\endgroup
  }}

\begin{document}

\begin{lrbox}{\mycd}
\begin{tikzcd}[font=\large, row sep=2.5em,arrows={line width=0.7pt}] 
    \mathbb{H} \arrow[r,"T"] 
    \arrow[d,"\Psi_T^*"'] & \mathscr{H} \\ 
    \mathsf{L}^2(\Omega,\mu) \arrow[r,"\mathscr{M}_F"'] 
    & \mathsf{L}^2(\Omega,\mu) \\
\end{tikzcd} 
\end{lrbox}

\begin{tikzpicture}[nodeformula/.style={rectangle,rounded corners=0.2cm,
    drop shadow={shadow xshift=1mm, shadow yshift=-1mm,opacity=1,
    on layer=background},
    draw=black,inner sep=2mm,ultra thick, text centered},
    nodepoint/.style={circle,draw=gray,fill=gray,inner sep=0.8mm},
    nodeoformula2/.style={nodeformula,fill=white,
        % top color=white, bottom color=white %<-as of now no effect
        },
    nodeoformula3/.style={nodeformula,fill=white,rectangle split, rectangle split parts=2,
        rectangle split part align={center,center}, 
        % top color=white, bottom color=white %<-as of now no effect
         },
    nodeoformula4/.style={nodeformula,%top color=white, bottom color=white,
        rectangle split,
        rectangle split parts=2,
        rectangle split part fill={#1}, 
        }]
  \node[nodeoformula2] (B2) {\usebox\mycd};
  \node[nodeoformula3,below=of B2] (B3) {  AAA   \nodepart{two} 
      \usebox\mycd};
  \node[nodeoformula4={red!75!black,red!5!white},below=of B3] (B4)
      {  AAA     \nodepart{two} 
      \usebox\mycd};
\end{tikzpicture}
\end{document}

enter image description here

  • Thank you very much for this elegant solution but I still have a problem – RiemannGauss Jan 21 at 18:56
  • If I replace the previous tikzcd as follows \begin{tikzcd}[font=\large, row sep=2.5em] \mathbb{H} \arrow[r,"T",line width=0.7pt] \arrow[d,"\Psi_T^*"',line width=0.7pt]&\mathscr{H} \\ \mathsf{L}^2(\Omega,\mu) \arrow[r,"\mathscr{M}_F"',line width=0.7pt] &\mathsf{L}^2(\Omega,\mu) \end{tikzcd} (+\usepackage{mathrsfs}, \usepackage{mathtools}) I have the error messages:1) Package tikz Error: Giving up on this path. Did you forget a semicolon?. I think the culprit is a tikzcd arrow in cell 2-1. 2) Extra }, or forgotten \endgroup. \end{tikzcd}. Do you have any idea why it happens? – RiemannGauss Jan 21 at 18:56
  • 1
    @RiemannGauss You only need to put \begin{lrbox}{\mycd} after \begin{document}. – Schrödinger's cat Jan 21 at 19:11
5

The comment of Zarko is correct: Nesting tikz can easily lead to problems. Therefore it would be better to refrain from nesting and e. g. just draw nodes or rectangles around it and use scopes for relative placement.

Nonetheless I made some adaptions to get rid at least of the placement problems in the third example.

Adaptation:

  • formatted code to make it more readable
  • use tikzpicture options [...] instead of multiple \tikzset{...}
  • remove options: text width=7cm, align=center from nodeoformula4

Code:

\documentclass{amsart}
\usepackage{tikz}
\usepackage{tikz-cd}
\usetikzlibrary{arrows,patterns,decorations.markings,shapes.geometric,positioning,shapes.geometric,backgrounds,patterns,shadows,calc,shapes.multipart}

\begin{document}
\begin{tikzpicture}[
    nodeoformula2/.style={
        rectangle,
        rounded corners=0.2cm,
        drop shadow={shadow xshift=1mm, shadow yshift=-1mm,opacity=1},
        draw=black,
        top color=white,
        bottom color=white,
        ultra thick,
        inner sep=4mm,
        text centered,
    },
    nodepoint/.style={circle,draw=gray,fill=gray,inner sep=0.8mm},
    nodeoformula3/.style={
        rectangle split,
        rectangle split parts=2, 
        rounded corners=0.2cm,
        drop shadow={shadow xshift=1mm, shadow yshift=-1mm,opacity=1},
        draw=black,
        top color=white,
        bottom color=white,
        ultra thick,
        rectangle split part align={center,center},
    },
    nodeoformula4/.style = {
        rectangle split,
        rectangle split parts=2,
        rectangle split part fill={#1}, 
        draw, rounded corners,
        %text width=7cm,
        %align=center,
        text=black,
        ultra thick,
    },
]

    \node[nodeoformula2] (B) at (0, 4) {
        \begin{tikzcd}[font=\large, row sep=2.5em]
        A  \arrow[r,"T",line width=0.7pt] \arrow[d,"\Psi_T^*"',line width=0.7pt]&B \\
        C  \arrow[r,"F"',line width=0.7pt] &D \arrow[u,"\Psi_T"',line width=0.7pt]
        \end{tikzcd}
    };
    \node[nodeoformula3] (B) at (0, 0) {
        AAA
        \nodepart{two}
        \begin{tikzcd}[font=\large, row sep=2.5em] 
        A  \arrow[r,"T",line width=0.7pt] \arrow[d,"\Psi_T^*"',line width=0.7pt]& B\\
        C  \arrow[r,"F"',line width=0.7pt] &D \arrow[u,"\Psi_T"',line width=0.7pt]
        \end{tikzcd}
    };
    \node[nodeoformula4={red!75!black,red!5!white}] (B) at (0, -4) {
        AAA
        \nodepart{two} 
        \begin{tikzcd}[font=\large, row sep=2.5em] 
        A  \arrow[r,"T",line width=0.7pt] \arrow[d,"\Psi_T^*"',line width=0.7pt]& B\\
        C  \arrow[r,"F"',line width=0.7pt] &D \arrow[u,"\Psi_T"',line width=0.7pt]
        \end{tikzcd}
    };
\end{tikzpicture}
\end{document}

Result:

enter image description here

5

As supplement to nice @dextraritas answer (+1):

  • distance between nodes are defined by use of \positioning,
  • all nodes have shadows
  • with \tikzcdset{...} are collected common features in the tikz-cd diagrams as are arrows style, font size and row separation
  • used are shortens \ar instead long name \arrows
  • arrows labels on opposite side are are shifted down for 1ex (for better looking diagrams)
  • styles of nodes are redefined (unified)
\documentclass{amsart}
\usepackage{tikz}
\usepackage{tikz-cd}
\usetikzlibrary{arrows.meta,
                backgrounds,
                calc,
                patterns, positioning,
                shadows, shapes.geometric, shapes.multipart}
%
\pgfdeclarelayer{foreground}
\pgfdeclarelayer{background}
   \pgfsetlayers{background,main,foreground}
%
\makeatletter
\def\tikz@extra@preaction#1{% suggested Mark Wibrow on c.t.t. (2010)
  {%
    \pgfsys@beginscope%
      \setbox\tikz@figbox=\box\voidb@x%
      \begingroup\tikzset{#1}\expandafter\endgroup%
      \expandafter\def\expandafter\tikz@preaction@layer
\expandafter{\tikz@preaction@layer}%
      \ifx\tikz@preaction@layer\pgfutil@empty%
      \path[#1];% do extra path
      \else%
      \begin{pgfonlayer}{\tikz@preaction@layer}%
      \path[#1];%
      \end{pgfonlayer}
      \fi%
      \pgfsyssoftpath@setcurrentpath\tikz@actions@path% restore
      \tikz@restorepathsize%
    \pgfsys@endscope%
  }%
}
\let\tikz@preaction@layer=\pgfutil@empty
\tikzset{preaction layer/.store in=\tikz@preaction@layer}
\makeatother

\begin{document}
\begin{tikzpicture}[
node distance =8mm and 2mm,
        base/.style = {draw, ultra thick, rounded corners=2mm, 
           text centered, inner sep=2mm,
           preaction layer=background, % prepare layer for multipart node dropped shadow
           drop shadow={shadow xshift=1mm, shadow yshift=-1mm, opacity=0.8}
                       },
nodeoformula2/.style= {base, fill=white,},
nodeoformula3/.style= {base, fill=white,
            rectangle split, rectangle split parts=2,
                       },
nodeoformula3/.default=white,
                ]
%%
\tikzcdset{every arrow/.style={draw, line width=0.8pt, ->},
           row sep/normal=2.5em,
           font=\large,
           }
%%%%
    \node[nodeoformula2] (A)    {
        \begin{tikzcd}
A  \ar[r,"T"] \ar[d,"\Psi_T^*"']    &   B \\
C  \ar[r,"F"']                      &   D \ar[u,"\Psi_T"']
        \end{tikzcd}
    };
    \node[nodeoformula3, below=of A] (B)    {AAA,
        \nodepart{two}
        \begin{tikzcd}
A  \ar[r,"T"] \ar[d,"\Psi_T^*"']    &   B  \\
C  \ar[r,"F"']                      &   D \ar[u,"\Psi_T" yshift=-1ex, ']
        \end{tikzcd}
    };
    \node (C) [nodeoformula3={red!75!black, red!5!white},
               below=of B]         (C)     {AAA
        \nodepart{two}
        \begin{tikzcd}
A  \ar[r,"T"] \ar[d,"\Psi_T^*"']    &   B   \\
C  \ar[r,"F"']                      &   D \ar[u,"\Psi_T" yshift=-1ex, ']
        \end{tikzcd}
    };
\end{tikzpicture}
\end{document}

enter image description here

Note: red background in the bottom node is artifact caused by nesting ˙tikzcd diagram in \tikz node. To eliminate it, you need different approach to draw last node or you need to find another way to emphasize its importance.

Addendum:

Corect result of your image can be obtain without nesting images in nodes. One way, to do this, is draw matrices (or tikzc diagrams`= on main layer, after than fit nodes on background layer a,d add shadows on the back background layer. Consequently code is a bit more complex:

\documentclass{amsart}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,
                backgrounds,
                calc,
                fit,
                matrix,
                positioning,
                quotes,
                shadows
                }
    \pgfdeclarelayer{foreground}
    \pgfdeclarelayer{background}
    \pgfdeclarelayer{back background}
   \pgfsetlayers{back background, background, main, foreground}

\begin{document}
    \begin{tikzpicture}[auto=right,
      node distance = 12mm,
  every edge/.style = {draw,-Straight Barb},
        boxF/.style = {draw, very thick, fill=white, fit=#1, rounded corners,
            inner xsep=4mm, inner ysep=2mm, outer sep=0pt,
            node contents={},
            drop shadow={shadow xshift=1mm, shadow yshift=-1mm, opacity=0.8}
                        },
   boxFA/.style args = {#1/#2}{fit=#2,
            inner xsep=4mm, inner ysep=2mm, outer sep=0pt,
            %node contents={},
            append after command={\pgfextra{\let\LN\tikzlastnode
            \draw[very thick, fill=#1, rounded corners, line cap=rect]
                (\LN.north west) |- (\LN.south) -| (\LN.north east);
            \draw[thick]
                (\LN.north west) -- (\LN.north east);
                }}% end after command
                                },
   boxFB/.style args = {#1/#2}{fit=#2, 
            inner xsep=0pt, outer sep=0pt,
            append after command={\pgfextra{\let\LN\tikzlastnode
            \draw[very thick, fill=#1, rounded corners, line cap=rect]
                (\LN.south west) |- ([yshift=3ex]\LN.south) -| (\LN.south east);
                }}
                                },
        mtrx/.style = {matrix of math nodes,
            ampersand replacement=\&,
            nodes={rectangle, minimum size=1.5em, inner sep=0pt,
                  font=\large},
            column sep=2.5em,
            row sep=2.5em,
            append after command={\pgfextra{\let\LN\tikzlastnode 
                   \path (\LN-1-1) edge["$T$" ']        (\LN-1-2)
                         (\LN-1-1) edge["$\Psi_T^*$"]   (\LN-2-1)
                         (\LN-2-1) edge["$F$"]          (\LN-2-2)
                         (\LN-2-2) edge["$\Psi_T^*$"]   (\LN-1-2);
                                }}% end after command
                    }
                    ]
% top
\matrix (m1) [mtrx=AAA]
{
A \& B  \\
C \& D  \\
};
\scoped[on background layer]%
    \node [boxF=(m1)];
% midle
\matrix (m2) [mtrx=AAA, below=of m1]
{
A \& B  \\
C \& D  \\
};
\scoped[on background layer]%
{
    \node (f1) [boxFA=white/(m2)] {};
\path   let \p1 = ($(f1.east)-(f1.west)$),
            \n1 = {veclen(\y1,\x1)} in
        node (f2) [boxFB=white/(f1.north west) (f1.north east),
                   above=0pt of f1] {AAA};
}
% bottom
\matrix (m3) [mtrx=AAA, below=of m2]
{
A \& B  \\
C \& D  \\
};
\scoped[on background layer]%
{
    \node (f3) [boxFA=red!5!white/(m3)] {};
\path   let \p1 = ($(f3.east)-(f3.west)$),
            \n1 = {veclen(\y1,\x1)} in
        node (f4) [boxFB=red!75!black/(f3.north west) (f3.north east),
                    above=0pt of f3] {AAA};
}
\begin{pgfonlayer}{back background}
\node [boxF=(f1) (f2), inner sep=0pt,
       drop shadow={shadow xshift=1mm, shadow yshift=-1mm, opacity=0.8}];
\node [boxF=(f3) (f4), inner sep=0pt,
       drop shadow={shadow xshift=1mm, shadow yshift=-1mm, opacity=0.8}] {};
\end{pgfonlayer}
\end{tikzpicture}
\end{document}

which gives:

enter image description here

Beside above solution also exist others, but it can serve as (good) starting point.

  • You correctly say that one should not nest tikzpictures, but then you go on and put a \path inside a \pgfextra{...}, which just opens another can of worms. – Schrödinger's cat Jan 21 at 2:59

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.