3

The rectangle split from the shapes.multipart can produce rectangles tightly stacked.

\documentclass[tikz]{standalone}
\usetikzlibrary{shapes.multipart}

\begin{document}
\begin{tikzpicture}
  \node[
    draw, fill=lightgray,
    rounded corners,
    rectangle split, rectangle split parts=3
  ] {
    first part
    \nodepart{two}second part
    \nodepart{three}\ldots
  };
\end{tikzpicture}
\end{document}

no gaps

But I would like to have gaps in between the parts like this. Rounded corners were added for emphasis.

gaps

All of them should be as wide as the widest of them, text with should not be fixed. They should be able to contain complex matter, like listings. Are multipart shapes the right approach? Would it be appropriate to define a custom shape?

How can rectangular nodes be stacked?

  • Do you really need tikz for that? – Bernard Oct 23 '15 at 12:00
  • I intend it to be part of a larger tikzpicture, so I sought out for answers in TikZ. But if you can persuade me with something else, feel free to do so. – XZS Oct 23 '15 at 12:06
5

I think this code, using tcolorbox and eqparbox should help. Eqparbox defines tagged boxes, so that all boxes with the same tag eventually all have the width of the widest of them (requires two compilations):

\documentclass{article}

\usepackage{tcolorbox}
\usepackage{eqparbox}

\begin{document}

\begin{center}
  \tcbox{\eqmakebox[P]{First Part}}

  \tcbox{\eqmakebox[P]{Second Part}}

  \tcbox{\eqmakebox[P]{$ \dots $}}
\end{center}

\end{document} 

enter image description here

  • This is a nice solution for isolated graphics. It could be used as node content in TikZ. Unfortunately, it is not suited for my case as I need to use anchors of the rectangles for positioning and edges. – XZS Oct 23 '15 at 13:32
  • 2
    @XZS Simply use this solution inside a rectangle split shape. – Gonzalo Medina Oct 23 '15 at 14:08
5

This solution defines a pic element which accepts an arbitrary comma-separated list of texts and puts them one after other vertically, and at the same time defines names for each "subnode":

\documentclass[tikz,margin=5pt]{standalone}
\usetikzlibrary{positioning,fit}

\tikzset{
    my split/.pic = {
        \coordinate (aux) at (0,0);
        \foreach \text [count=\i] in {#1} {
          \node[below=of aux, draw, fill] (-\i) {\text};
          \coordinate (aux) at (-\i.south);
        }
    }
}

It can be used from a tikz picture like this:

\draw pic[options] (NAME) at (coordinates) {my split={Text,for each,subnode}};

In options you can specify aspects such as the fill color, the rounded corners, the distance among nodes, and the width of each node (if this one is not given, each node will have its own "natural width").

Once the pic is drawn, you have node names: (NAME-1), (NAME-2), etc for each of the subnodes, which can be used to connect them with other parts of the tikz figure.

For example:

\begin{document}
\tikzset{
  my style/.style={rounded corners, text width=3cm, node distance=1mm, fill=black!20}
}
\begin{tikzpicture}
\draw pic[my style] (A) at (0,0)
    {my split={A First text, A Second Text, A Third Text}};
\draw  pic[my style, fill=orange!20] (B) at (4, 0.5)
    {my split={B First line, B second line, $\dots$}};
\draw[-latex] (A-2.east) -- (B-1.west);
\end{tikzpicture}
\end{document}

Produces:

Result

  • You could combine this with \eqmakebox as in Bernard's answer to lift the restriction on declaring text width (the question mentions that text width should not be declared explicitly). – Gonzalo Medina Oct 23 '15 at 14:29
  • Can these nodes also be used for alignment? I would, for example, like to have "First line" right=5ex of "Third Text", placing the other "line" nodes accordingly. – XZS Oct 24 '15 at 22:43
3

Another solution. This one combines eqmakebox and a TiKZ matrix.

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

\usepackage{eqparbox}
\usetikzlibrary{matrix, positioning}

\begin{document}

\begin{tikzpicture}
  \matrix (A) [matrix of nodes, nodes={draw, rounded corners, fill=gray!30}, row sep=1mm]
  {\eqmakebox[P]{First Part}\\
  \eqmakebox[P]{Second Part}\\
\eqmakebox[P]{$ \dots $}\\
};

  \matrix (B) [matrix of nodes, nodes={draw, rounded corners, fill=green!30}, row sep=1mm, above right= 3mm and 5mm of A.east]
  {\eqmakebox[P]{First Part}\\
  \eqmakebox[P]{Second Part}\\
\eqmakebox[P]{$ \dots $}\\
};

\draw (A-1-1) to[out=0, in=180] (B-1-1);
\draw (A-2-1) to[out=0, in=180] (B-2-1);
\end{tikzpicture}

\end{document} 

enter image description here

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.