How to align nodes in a layered block diagram in tikz?
Here is a proposal following the end of section 5.1 of the pgfmanual
. In addition the positioning
library is loaded.
\documentclass[tikz]{standalone}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}[every node/.append style={minimum height=7mm,
text depth=0.25ex,draw},node distance=9mm and 3mm]
\node (a1) { A1 };
\node (a2) [right=of a1] { A2gq };
\node (a3) [right=of a2] { A3 };
\draw[red] (a1.base -| a1.west) -- (a3.base -| a3.east);
\node (b1) [below of=a1] { B1 };
\node (b2) [right=of b1] { B2 };
\node (b3) [right=of b2] { B3gq };
\node (b4) [right=of b3] { B4 };
\draw[red] (b1.base -| b1.west) -- (b4.base -| b4.east);
\node (c1) [below of=b1] { C1 };
\node (c2) [right=of c1] { C2gq };
\node (c3) [right=of c2] { C3 };
\end{tikzpicture}
\end{document}
The red lines are just for illustration and should be removed of course.
UPDATE: Make sure that the outer ends of the rows are aligned. EDIT: Unified the positioning syntax, big thanks to @sgmoye!
\documentclass[tikz]{standalone}
\usetikzlibrary{positioning,fit}
\begin{document}
\begin{tikzpicture}[every node/.append style={minimum height=7mm,
text depth=0.25ex,draw},node distance=3mm and 3mm]
\node (b1) { B1 };
\node (b2) [right=of b1] { B2 };
\node (b3) [right=of b2] { B3gq };
\node (b4) [right=of b3] { B4 };
\node (a1) [above=of b1] { A1 };
\node (f1) [inner sep=-\pgflinewidth*0.5pt,fit=(b2.west|-a1.north) (b3.east|-a1.south)]{};
\node (a3) [above=of b4] { A3 };
\path (a1) -- (a3) node[midway,draw=none] (a2) { A2gq };
\node (c1) [below=of b1] { C1 };
\node (f1) [inner sep=-\pgflinewidth*0.5pt,fit=(b2.west|-c1.north) (b3.east|-c1.south)]{};
\node (c3) [below=of b4] { C3 };
\path (c1) -- (c3) node[midway,draw=none] (c2) { C2gq };
\end{tikzpicture}
\end{document}
ADDENDUM: A not so fiddly solution. No packages. Just for fun.
\documentclass{article}
\begin{document}
\begin{minipage}{5cm}
\fbox{ A1 }\hfill\fbox{ A2gq }\hfill\fbox{ A3 }\\[4mm]
\fbox{ B1 }\hfill\fbox{ B2 }\hfill\fbox{ B2gq }\hfill\fbox{ B4 }\\[4mm]
\fbox{ C1 }\hfill\fbox{ C2gq }\hfill\fbox{ C3 }
\end{minipage}
\end{document}
ADDENDUM: A bit more seriously: if you wish to combine the nice feature of \hfill
with TikZ, then you may want to have a look at this snippet.
\documentclass{article}
\usepackage{tikz}
\newcounter{tikzbox}
\newcommand{\tikzbox}[2][]{\stepcounter{tikzbox}
\tikz[remember picture]{\node[draw,minimum height=7mm,
text depth=0.25ex,#1](tikzbox-\thetikzbox){#2};}}
\begin{document}
\begin{minipage}{5cm}
\tikzbox{A1}\hfill\tikzbox{A2gq}\hfill\tikzbox{A3}\\[4mm]
\tikzbox[alias=pferd]{B1}\hfill\tikzbox[alias=hase]{B2}\hfill\tikzbox{B2gq}\hfill\tikzbox{B4}\\[4mm]
\tikzbox{C1}\hfill\tikzbox{C2gq}\hfill\tikzbox{C3}
\end{minipage}
\tikz[overlay,remember picture]{%
\draw[thin,red] (tikzbox-1.base) -- (tikzbox-3.base);
\draw[thick,-latex] (pferd) -- (hase);
}
\end{document}
The red line is just for illustration, and there is some more serious application as well. The nodes get auto-labeled, but you can give them your own names using alias
.
I just discovered TikZ's execute at begin node
function. Very handy. It is used on pages 79 and 80 of the TikZ user guide, though I cannot find it discussed there. This essentially does what @marmot proposes but uses a \strut
to accomplish it.
\documentclass[tikz]{standalone}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}[every node/.style={draw,execute at begin node=\strut}]
\node (a1) { A1 };
\node (a2) [right=of a1] { A2gq };
\node (a3) [right=of a2] { A3 };
\node (b1) [below=of a1] { B1 };
\node (b2) [right=of b1] { B2 };
\node (b3) [right=of b2] { B3gq };
\node (b4) [right=of b3] { B4 };
\node (c1) [below=of b1] { C1 };
\node (c2) [right=of c1] { C2gq };
\node (c3) [right=of c2] { C3 };
\end{tikzpicture}
\end{document}
Update
As I am not a fan of excessive markup, that word 'fiddly' got my attention, as did @marmot's non-TikZ solution (smart!). So I offer this:
\documentclass{article}
\usepackage{tikz}
%% #1 the distance over which nodes are spread;
%% #2 comma-separated list of node contents.
\newcommand{\stretchtowidth}[2]{%
\begingroup
\tikzset{every node/.style={draw}}%
\hbox to #1{%
\foreach \n in {#2}{\tikz\node{\strut\n};\hfill}\unskip}%
\endgroup
}
\begin{document}
\stretchtowidth{1.25in}{A1,A2gq,A3}
\medskip
\stretchtowidth{1.25in}{B1,B2,B3gq,B4}
\medskip
\stretchtowidth{1.25in}{C1,C2gq,C3}
\end{document}
A solution using the chains
library.
\documentclass[tikz]{standalone}
\usetikzlibrary{chains}
\begin{document}
\begin{tikzpicture}[
start chain=A going right,
start chain=B going right,
start chain=C going right,
outer sep=0pt,
inner sep=.2em,
node distance=1.6em and .25em,
every node/.style={draw, anchor=base, text height=0.8em, text depth=0.25ex}]
\node (a1) [on chain=A] {A1};
\node [on chain=A] {A2gq};
\node [on chain=A] {A3};
\node (b1) [on chain=B, below of=a1] {B1};
\node [on chain=B] {B2};
\node [on chain=B] {B3gq};
\node [on chain=B] {B4};
\node [on chain=C, below of=b1] {C1};
\node [on chain=C] {C2gq};
\node [on chain=C] {C3};
\end{tikzpicture}
\end{document}