# TikZ + PGF: Aligning nodes with relative positioning

I want to draw my physical data center layout in LaTeX using TikZ and PGF but I'm facing a problem aligning my racks correctly.

In the MWE I've drawn three racks, two of which (network equipment) are a bit deeper than the first (server equipment). Their front should be aligned which I indicated using a red line in the following screenshot

The MWE:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}

\tikzset{server rack/.style={
draw,
anchor=north west,
minimum height=7.5mm,
minimum width=10.7mm}}
\tikzset{network rack/.style={
draw,
anchor=north west,
minimum height=7.5mm,
minimum width=12mm}}

\begin{document}

\begin{tikzpicture}[node distance=0mm]
\draw[step=6mm,gray,very thin] (0,0) grid (4.2,4.2);
\node[server rack]  (C17) at (1.33,3) {C17};
\node[network rack] (D17) [below=of C17] {D17};
\node[network rack] (E17) [below=of D17] {E17};

\draw[thick,red] (2.4,3) -- (2.4,0);
\end{tikzpicture}

\end{document}

• That is the point. The width indicates how deep the rack is, and one should be deeper (thus wider) than the other. – Tom Mar 10 '17 at 17:21
• Hence do you want only to right align the nodes? – CarLaTeX Mar 10 '17 at 17:24
• Correct. At the red line, they should be aligned, so the "network" racks will stick out at the "back", i.e. stick out on the left side of the rectangles, in this case. – Tom Mar 10 '17 at 17:25
• @Tom, you can also vote up my answer, in addition to accepting it, if you want :D – Enlico Mar 10 '17 at 18:12

Explanation as suggested by @Ignasi

When you use the options below=of somenode et similia provided by the positioning library, e.g. when you create a node by

\node[below left=of A.south east] (B) {some text};


you are basically positioning a specific anchor (implicitly north east, through the explicit option below left=of) of the node you are creating (B), with respect to a specific anchor (explicitly south east) of an already existing node (A).

NOTE If no anchor is specified for the existing node then the anchor "opposite" to the one chosen for the new node is chosen (e.g. below left=of A] specifies the north east anchor for B, so south west is chosen for A; it has the same effect of below left=of A.south west).

Obviously the distance between the nodes' anchors you use in relative positioning can be set through node distance. In the following figure (with the code to generate it attached) I graphically explain the preceding words. Setting node distance=0 (and removing all gray nodes) produces your attempt on the left and the desired result on the right.

\documentclass[tikz]{standalone}

\usetikzlibrary{positioning}

\tikzset{server rack/.style={
draw,
minimum height=7.5mm,
minimum width=10.7mm}}
\tikzset{network rack/.style={
draw,
minimum height=7.5mm,
minimum width=12mm}}

\begin{document}

\begin{tikzpicture}[node distance=2cm]

\node[server rack]  (A) at (.5,4) {A};
\node[network rack] (B) [below=of A] {B};
\node[network rack] (C) [below=of B] {C};
\draw[|<->|, gray] (A.south) -- (B.north) node[at start, anchor=north west, inner ysep=0] {\tiny \verb|A.south|}
node[midway,   anchor=west,       inner ysep=0] {\tiny \verb|(B) [below=of A]|'s effect}
node[midway,   above, rotate=180, inner ysep=2pt, sloped] {\tiny \verb|node distance|}
node[at end,   anchor=south west, inner ysep=0] {\tiny \verb|B.north|};
\draw[|<->|, gray] (B.south) -- (C.north) node[at start, anchor=north west, inner ysep=0] {\tiny \verb|B.south|}
node[midway,   anchor=west,       inner ysep=0] {\tiny \verb|(C) [below=of B]|'s effect}
node[midway,   above, rotate=180, inner ysep=2pt, sloped] {\tiny \verb|node distance|}
node[at end,   anchor=south west, inner ysep=0] {\tiny \verb|C.north|};

\node[server rack]  (A) at (5,4) {A};
\node[network rack] (B) [below left=of A.south east] {B};
\node[network rack] (C) [below=of B] {C};
\draw[|<->|, gray] (A.south east) -- (B.north east) node[at start, anchor=north west, inner ysep=0] {\tiny \verb|A.south|}
node[midway,   anchor=west,       inner ysep=0] {\tiny \verb|(B) [below left=of A.south east]|'s effect}
node[midway,   above,             inner ysep=2pt, sloped] {\tiny \verb|node distance|}
node[at end,   anchor=south west, inner ysep=0] {\tiny \verb|B.north|};
\draw[|<->|, gray] (B.south) -- (C.north) node[at start, anchor=north west, inner ysep=0] {\tiny \verb|B.south|}
node[midway,   anchor=west,       inner ysep=0] {\tiny \verb|(C) [below=of B]|'s effect}
node[midway,   above, rotate=180, inner ysep=2pt, sloped] {\tiny \verb|node distance|}
node[at end,   anchor=south west, inner ysep=0] {\tiny \verb|C.north|};

\end{tikzpicture}

\end{document}


This is the solution you're looking for, I think.

• No change is needed to the first block, since... it's the first one! :D
• Since the third block is equal in size to the second one, no change is needed either.
• The second block: it should be positioned on the left of the right (i.e. west) side of the first block.

The code becomes

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}

\tikzset{server rack/.style={
draw,
anchor=north west,
minimum height=7.5mm,
minimum width=10.7mm}}
\tikzset{network rack/.style={
draw,
anchor=north west,
minimum height=7.5mm,
minimum width=12mm}}

\begin{document}

\begin{tikzpicture}[node distance=0mm]
\draw[step=6mm,gray,very thin] (0,0) grid (4.2,4.2);
\node[server rack]  (C17) at (1.33,3) {C17};
\node[network rack] (D17) [below left=of C17.south east] {D17}; % <-- modified line
\node[network rack] (E17) [below=of D17] {E17};

%\draw[thick,red] (2.4,3) -- (2.4,0);
\end{tikzpicture}

\end{document}

• This is so simple, I have no clue why I didn't think of this. I did try putting [below=of C17.south east] and playing with the anchor in the \tikzset but didn't think of using below left. – Tom Mar 10 '17 at 18:18
• Yes, I know. Easy things never come to our mind when we need them! – Enlico Mar 10 '17 at 18:24
• May be you could explain that different positioning options use different anchors: below uses north while below left uses north east. This explains that original code aligned all nodes at its central axis while yours adjust top right corner of second node to bottom right one of first node. – Ignasi Mar 10 '17 at 18:39
• Note: below of=... is not provided by positioning library (it's just an old and deprecated syntax). below=of ... is provided by positioning library. – Paul Gaborit Mar 11 '17 at 9:40
• for a node distances other than 0mm, say 1cm, one can use below left=1cm and 0 of C17.south east. Yes, yshift is first, presumably because below is written before left. – golvok Dec 10 '18 at 21:31

Try with \matrix:

\documentclass{article}
\usepackage{tikz}
%\usetikzlibrary{positioning} % not needed in this solution

\tikzset{server rack/.style={
draw,
minimum height=7.5mm,
minimum width=10.7mm}}
\tikzset{network rack/.style={
draw,
minimum height=7.5mm,
minimum width=12mm}}

\begin{document}

\begin{tikzpicture}[node distance=0mm]
\draw[step=6mm,gray,very thin] (0,0) grid (4.2,4.2);

\matrix[anchor=base east]  at (2.5,1) {
\node[server rack]  (C17) {C17}; \\
\node[network rack] (D17) {D17}; \\
\node[network rack] (E17) {E17}; \\ };

\draw[thick,red] (2.4,3) -- (2.4,0);
\end{tikzpicture}

\end{document}


• It sure works so I should accept it as an answer but I was hoping for a solution using relative positioning. I think that would look "cleaner." Either way, thanks for the suggestion! If no other options are presented, I'll accept this one as the correct answer. – Tom Mar 10 '17 at 17:56
• @Tom Don't worry, I think some TikZ expert will find a better solution. – CarLaTeX Mar 10 '17 at 17:57