# Top-align text in a TikZ node of given size for single- and multiline case

I would like to set text in a TikZ node of maximum width and minimum height, i.e. the node cannot grow horizontally (but shrink for short text) but it can grow vertically (if the text exceeds the minimum height).

Using the varwidth package this looks not too difficult, but the problem is, that I would like to top-align the enclosed text. The alignment should work for single lines of text as well as for more than one text line.

Tik/ doesn't seem to know any text top-align function but instead suggests the use of the text depth= key. Unfortunately, that doesn't seem to work in a multi-line vs. single-line comparison.

You can use the following code for an example:

\documentclass{scrreprt}

\usepackage{tikz}
\usetikzlibrary{positioning}

\usepackage{varwidth}

\begin{document}

\begin{tikzpicture}
\node (left) [minimum height=2cm,inner sep=0,shape=rectangle,draw=black] {%
\begin{varwidth}{3cm}%
Short text%
\end{varwidth}%
};
\node at (left.north east) [anchor=north west,minimum height=2cm,inner sep=0,shape=rectangle,draw=black] {%
\begin{varwidth}{3cm}%
Somehow a longer text for testing%
\end{varwidth}%
};
\end{tikzpicture}

\vspace{1cm}

\begin{tikzpicture}
\node (left) [text depth=2cm,inner sep=0,shape=rectangle,draw=black] {%
\begin{varwidth}{3cm}%
Short text%
\end{varwidth}%
};
\node at (left.north east) [anchor=north west,text depth=2cm,inner sep=0,shape=rectangle,draw=black] {%
\begin{varwidth}{3cm}%
Somehow a longer text for testing%
\end{varwidth}%
};
\end{tikzpicture}

\vspace{1cm}

\begin{tikzpicture}
\node (left) [text depth=2cm,text height=0,inner sep=0,shape=rectangle,draw=black] {%
\begin{varwidth}{3cm}%
Short text%
\end{varwidth}%
};
\node at (left.north east) [anchor=north west,text depth=2cm,text height=0,inner sep=0,shape=rectangle,draw=black] {%
\begin{varwidth}{3cm}%
Somehow a longer text for testing%
\end{varwidth}%
};
\end{tikzpicture}

\end{document}


The output looks like this:

• The first two boxes show how varwidth does its job by growing the second box up to 3cm width and then breaking the line.

• The second two boxes are my attempt to solve it by setting text depth=2cm but as you can see, this grows one box vs. the other.

• The third illustration is an experiment to find out why text depth is not working as I would expect. Setting text height=0 centers the text vertically on the textbox center and the boxes are of correct height. But now the text overflows on the top.

Desired outcome would be a box of height of 2cm with the text aligned on top. Maybe I'm missing something obvious?

Edit: I found a crude way to bottom-align

Reading In TikZ, is it possible to nest nodes? I got the idea of nesting tikzpicture environments. This led to a crude way of bottom-aligning, but no top aligning.

The code looks like this (works with my example document from above):

\begin{tikzpicture}
\node (left) [minimum height=2cm,inner sep=0,text height=2cm,text depth=0,shape=rectangle,draw=black] {%
\begin{tikzpicture}
\node [minimum height=0,inner sep=0,text height=,text depth=,shape=rectangle,draw=red] {%
\begin{varwidth}{3cm}%
Short text%
\end{varwidth}%
};
\end{tikzpicture}%
};
\node at (left.north east) [minimum height=2cm,inner sep=0,text height=2cm,text depth=0,anchor=north west,shape=rectangle,draw=black] {%
\begin{tikzpicture}
\node [minimum height=0,inner sep=0,text height=,text depth=,shape=rectangle,draw=red] {%
\begin{varwidth}{3cm}%
Somehow a longer text for testing%
\end{varwidth}%
};
\end{tikzpicture}%
};
\end{tikzpicture}


It is crude because it doesn't take the baseline into account (could maybe be fixed with \strut) and because it nests the environment, which actually requires to reset all parameters on the inside as they are inherited from the outside.

You could work around this by using two nodes instead of one: The first contains just the text, the second uses the fit library to draw a rectangle of a specified minimum height around the text.

I've written a style called add rectangle that takes an optional height and uses the append after command style to add a second node directly after the text node.

In order to fill the background, you can use the backgrounds library and place the rectangle on the background layer using the pgfonlayer environment.

\documentclass{scrreprt}

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

\usepackage{varwidth}

\tikzset{
alias=tempname,
append after command={
; \begin{pgfonlayer}{background}
\node [
fill=yellow,
draw=yellow!80!black,
fit={(tempname) ($(tempname.north)+(0,-#1)$)},
inner sep=0pt] {};
\end{pgfonlayer} \path
}
},
}

\begin{document}

\begin{tikzpicture}
\node (left) [
] {%
\begin{varwidth}{3cm}%
Short%
\end{varwidth}%
};

\node at (left.north east) [name=middle,anchor=north west,add rectangle=2cm] {%
\begin{varwidth}{3cm}%
Somehow a longer text for testing%
\end{varwidth}%
};

\node at (middle.north east) [anchor=north west,add rectangle=2cm] {%
\begin{varwidth}{3cm}%
Somehow a longer text for testing. This is a really long text that will stretch the box vertically.%
\end{varwidth}%
};
\end{tikzpicture}

\end{document}

• Thanks so much, works very well. In order to make sure that the baseline is respected, I use a \strut as well and now it's perfect. – kongo09 Aug 24 '11 at 14:49