# TikZ: Background rectangles with equal width but 'fitting' height

I'm trying to make sort of a flow chart for a series of steps, but these steps are also grouped, and I'd like my diagram to reflect that. So I'm using the pgfonlayer/background environment to draw rectangles around these groups.

I found a similiar example that uses the fit parameter to find the right dimensions.

That example works nicely except for the fact that groups do not have an equal width, so the rectangles don't look very nice:

That's the code for that (elicit is the first node "Wissenserhebung"):

\begin{pgfonlayer}{background}
\node [background, fit=(elicit)] {};
% others similiar
\end{pgfonlayer}

Then, I found another way to do it, with rectangles and lots of calculations:

[nice example][2]

\draw [background] ($(elicit.north west)-(0.2,-0.2)$) rectangle ($(matrix.east)!(elicit.south east)!(matrix.east)+(0.2,-0.2)$);
\draw [background] ($(elicit.north west)!(interpret.north west)!(elicit.north west)-(0.2,-0.2)$) rectangle ($(matrix.east)!(model.south east)!(matrix.east)+(0.2,-0.2)$);
\draw [background] ($(elicit.north west)!(representation.north west)!(elicit.north west)-(0.2,-0.2)$) rectangle ($(matrix.east)!(representation.south east)!(matrix.east)+(0.2,-0.2)$);

With that code, I get nice rectangles, but they don't seem to be nodes so I cannot attach text to them.

Is there a 'canonical' way of getting these rectangles with an equal width but fitting to the height of the nodes inside and able to get text attached? I found posts about modifying bounding rectangles, but I'm not sure if or how that could help me here.

This is the full code (minus style definitions):

\begin{tikzpicture}
\matrix (matrix) [row sep=0.5cm,column sep=0.5cm] {
\node (elicit) [schritt] {Wissenserhebung}; & \\
\node (interpret) [schritt] {Interpretation}; & \\
& \node (model) [schritt] {Modellierung}; \\
\node (representation) [schritt] {Repräsentation}; & \\
\node (integration) [schritt] {Integration}; & \\
\node (maintenance) [schritt] {Wartung}; & \\
};

\path[->]
(elicit) edge (interpret)
(interpret) edge node[right] {\hspace{.35cm}\tiny Modellbasierter Ansatz} (model)
(interpret) edge node[right] {\tiny Rapid Prototyping} (representation)
(model) edge (representation)
(representation) edge (integration)
(integration) edge (maintenance);
\begin{pgfonlayer}{background}
% ugly, but nodes
%\node [background, fit=(elicit)] {};
%\node [background, fit=(interpret) (model)] {};
%\node [background, fit=(representation)] {};

% no nodes, but correct width
%\draw [background] ($(elicit.north west)-(0.2,-0.2)$) rectangle ($(matrix.east)!(elicit.south east)!(matrix.east)+(0.2,-0.2)$);
%\draw [background] ($(elicit.north west)!(interpret.north west)!(elicit.north west)-(0.2,-0.2)$) rectangle ($(matrix.east)!(model.south east)!(matrix.east)+(0.2,-0.2)$);
%\draw [background] ($(elicit.north west)!(representation.north west)!(elicit.north west)-(0.2,-0.2)$) rectangle ($(matrix.east)!(representation.south east)!(matrix.east)+(0.2,-0.2)$);
\end{pgfonlayer}
\end{tikzpicture}
-
Please make sure that all images are uploaded using the official stackexchange interface, i.e. the image icon on top of the text field (shortcut: CTRL+G). This ensures that all images are always accessible and do not get deleted. If you don't have enough reputation (10 rep) than simply remove the ! in front of the image code to turn it into a link. A moderator or high rep user can then include the image (by simply adding the ! again) for you. –  Martin Scharrer Jun 28 '11 at 11:52
@Martin thanks, I just changed the image. –  a3li Jun 28 '11 at 12:07
It would be good if you could post a full compilable, minimal example. It should start from \documentclass and include all style definitions necessary, so it can just be copied and pasted into a new document by people who want to try out the code. –  Jake Jun 28 '11 at 12:59

You can use nodes with the fit library by adding coordinates to each of the fit lists that lie on the left and right borders of the bounding box, but at the same vertical position as the nodes you want to highlight. You can do this with the calc library and its syntax ($(A)!(C)!(B)$), which projects the point (C) on the line from (A) to (B).

In the example below, I've used a script that takes a node name as an argument and returns three coordinates: The node itself, and its projection on the left and right borders of the bounding box. In order to make the new boxes all the same width, the bounding box needs to be "frozen", so one box doesn't influence the size of the next. You can do this by issuing \path [use as bounding box] (current bounding box.north west) (current bounding box.south east) before the first background box, which stops the updating of the bounding box.

\documentclass{article}

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

\begin{document}

\tikzset{
schritt/.style={
draw,
rounded corners,
fill=blue!20,
inner xsep=2em,
},
background/.style={
draw,
fill=yellow!30,
align=right
}
}

% Returns three nodes: The argument, and the projections of the argument on the left and right borders of the bounding box
\newcommand{\extendnode}[1]{
(#1)
($(current bounding box.north east)!(#1)!(current bounding box.south east)$)
($(current bounding box.north west)!(#1)!(current bounding box.south west)$)
}

\begin{tikzpicture}
\matrix (matrix) [row sep=0.5cm,column sep=0.5cm] {
\node (elicit) [schritt] {Wissenserhebung}; & \\
\node (interpret) [schritt] {Interpretation}; & \\
& \node (model) [schritt] {Modellierung}; \\
\node (representation) [schritt] {Repräsentation}; & \\
\node (integration) [schritt] {Integration}; & \\
\node (maintenance) [schritt] {Wartung}; & \\
};

\path[->]
(elicit) edge (interpret)
(interpret) edge node[right] {\hspace{.35cm}\tiny Modellbasierter Ansatz} (model)
(interpret) edge node[right] {\tiny Rapid Prototyping} (representation)
(model) edge (representation)
(representation) edge (integration)
(integration) edge (maintenance);

\begin{pgfonlayer}{background}

\path [use as bounding box] (current bounding box.north west) (current bounding box.south east); % Freeze current bounding box
\node [fit={\extendnode{elicit}}, background] {First};
\node [fit={\extendnode{interpret} (model)}, background] {Second};
\node [fit=\extendnode{representation}, background] {Third};
\node [fit=\extendnode{integration}, background] {Fourth};
\node [fit=\extendnode{maintenance}, background] {Fifth};

\end{pgfonlayer}
\end{tikzpicture}

\end{document}

-
Works great, thanks :) Sorry I didn't update my example, I missed your comment. –  a3li Jul 3 '11 at 10:14