[Tex/LaTex] How to have a node’s width match another’s height

tikz-pgfwidth

I have the following situation:

a bar whose width should match the height of another node

Here, I would like the rotated node to automatically match the height of the text node to its left, automatically growing or shrinking depending on the amount of text/line count in it. Right now, the hard-coded 8em only fits almost and needs constant care in case of changing text contents.

I assume that the fit library could help me here, but with my limited tikz code-foo I could only get misspelled pgf key errors and infinite compiles.

Here's the image as an MWE:

\documentclass{article}
\usepackage{tikz}
\usepackage{varwidth}
\usetikzlibrary{positioning,shapes}

\begin{document}
\begin{tikzpicture}[%
  node distance=2em,
  textbox/.style={rectangle split, rectangle split parts=2, 
                  rectangle split part fill={black!90,black!5},
                  rectangle split part align=base,
                  draw=gray,align=center},
  barstyle/.style={fill=black!90,text=white,align=center,inner ysep=6pt,rotate=90}]

\node[barstyle,minimum width=8em] % THIS should match height of text node automatically
  (bar) {A Bar!};

\node[textbox,left=of bar.north] (textnode) {%
  {\color{white} Input}
  \nodepart{two}
  \begin{varwidth}{.8\columnwidth}
    Some pretty\\
    drawn-out text\\
    much too long\\
    to fit on a single\\
    line.
  \end{varwidth}};
\end{tikzpicture}
\end{document}

Best Answer

You can use fit library to compute node's height. But with fitting nodes, it's better to add its contents with the label option.

Following code defines a barstyle style with two arguments, the first one is the original node which is used to get its height while the second is the node contents.

\documentclass{article}
\usepackage{tikz}
\usepackage{varwidth}
\usetikzlibrary{positioning,shapes, fit}

\begin{document}
\begin{tikzpicture}[%
  node distance=2em,
  textbox/.style={rectangle split, rectangle split parts=2, 
                  rectangle split part fill={black!90,black!5},
                  rectangle split part align=base,
                  draw=gray,align=center},
  barstyle/.style 2 args={fill=black!90,
            minimum width=3em, 
            fit={(#1.south) (#1.north)}, inner ysep=0pt, label={[rotate=90, white]center:#2}
    }]

\node[textbox] (textnode) {%
  {\color{white} Input}
  \nodepart{two}
  \begin{varwidth}{.8\columnwidth}
    Some pretty\\
    drawn-out text\\
    much too long\\
    to fit on a single\\
    line.
  \end{varwidth}};

\node[barstyle={textnode}{A Bar!}, right=of textnode] (bar) {};

\node[textbox, below= of textnode] (textnode2) {%
  {\color{white} Input}
  \nodepart{two}
  \begin{varwidth}{.8\columnwidth}
    Some pretty 
    drawn-out text\\
    much too long 
    to fit on a single\\
    line.
  \end{varwidth}};

\node[barstyle={textnode2}{A Bar!}, right=of textnode2] (bar2) {};

\end{tikzpicture}
\end{document}

nodes whose heights match those of another node

2nd solution:

A completely different solution could be to use \tcbsetmacrotoheightofnode or \tcbsetmacrotowidthofnode macros from skins library in tcolorbox (see: 12.9 Extracting node dimensions) package:

\tcbsetmacrotoheightofnode{\myheight}{textnode2}

saves height of textnode2 node in macro \myheight which can be used in minimum height|width|size option from other nodes.

\documentclass{article}
\usepackage{tikz}
\usepackage{varwidth}
\usetikzlibrary{positioning,shapes}
\usepackage[skins]{tcolorbox}

\begin{document}
\begin{tikzpicture}[%
  node distance=2em,
  textbox/.style={rectangle split, rectangle split parts=2, 
                  rectangle split part fill={black!90,black!5},
                  rectangle split part align=base,
                  draw=gray,align=center},
  barstyle/.style={fill=black!90, text=white, align=center, inner ysep=6pt, rotate=90}
  ]

\node[textbox] (textnode) {%
  {\color{white} Input}
  \nodepart{two}
  \begin{varwidth}{.8\columnwidth}
    Some pretty\\
    drawn-out text\\
    much too long\\
    to fit on a single\\
    line.
  \end{varwidth}};

  \tcbsetmacrotoheightofnode{\myheight}{textnode}

    \node[barstyle, minimum width=\myheight, right= of textnode, anchor=north] (bar) {A Bar!};

\node[textbox, below= of textnode] (textnode2) {%
  {\color{white} Input}
  \nodepart{two}
  \begin{varwidth}{.8\columnwidth}
    Some pretty 
    drawn-out text\\
    much too long 
    to fit on a single\\
    line.
  \end{varwidth}};

  \tcbsetmacrotoheightofnode{\myheight}{textnode2}

    \node[barstyle, minimum width=\myheight, right=of textnode2, anchor=north] (bar2) {A Bar!};

\end{tikzpicture}
\end{document}