# Non-vertically-centered TikZ matrix of nodes cell content

How can you make the matrix cell contents aligned to the top? I am using plain format with XeTeX.

\input tikz
\usetikzlibrary{matrix}
\hbox{I'd like for the cells to be top-aligned}\cases{ \tikzpicture[ a/.style={draw=green!50!black,text width=3.5cm, text height=1.5cm,text depth=1.5cm,minimum size=3.5cm, anchor=base, inner sep=0pt,outer sep=0pt}, m/.style={matrix of nodes,inner sep=2pt,outer sep=0pt,nodes=a, ampersand replacement=\&,row sep=0pt,column sep=0pt,draw=black!50} ] \parindent0pt \matrix[m] (mx) { Hey, this is a node with a break\break and stuff\& And another one with it. Milkshakes are yummy when the sun is shining\\ Let's see what happens; I'm trying to find the logic\& Does it break when all these cells have different amount of text?\\ }; \draw[very thick,red!50] (mx.north)--(mx.south) (mx.west)--(mx.east); \endtikzpicture } \hbox{Yes it does}
\bye


After @Gonzalo's comment to change text height/depth:

\input tikz
\usetikzlibrary{matrix}
\tikzpicture[
a/.style={draw=green!50!black,text width=3.5cm,
text height=0pt,text depth=2.5cm,minimum size=3.5cm,
anchor=base,
inner sep=0pt,outer sep=0pt},
m/.style={matrix of nodes,inner sep=2pt,outer sep=0pt,nodes=a,
ampersand replacement=\&,row sep=0pt,column sep=0pt,draw=black!50}
]
\parindent0pt
\matrix[m] (mx) {
Hey, this is a node with a break\break and stuff\&
And another one with it. Milkshakes are yummy when the sun is shining\\
Let's see what happens; I'm trying to find the logic\&
Does it break when all these cells have different amount of text?\\
};
\draw[very thick,red!50] (mx.north)--(mx.south) (mx.west)--(mx.east);
\endtikzpicture
\bye


-
Using text height and text depth. Change your settings to text height=0cm, text depth=2.5cm,. – Gonzalo Medina Jun 12 '11 at 15:12
Try anchor=north in the a style. – Loop Space Jun 12 '11 at 15:22
I forgot that you are using pdftex; my suggestion works with pdflatex, but gives another result with pdftex. I will shortly delete these two comments. – Gonzalo Medina Jun 12 '11 at 15:22
@Andrew: there is no visible change with anchor=north – morbusg Jun 12 '11 at 15:23
@Gonzalo: please, don't. I forgot to specify which engine/format I'm using. I updated the question. – morbusg Jun 12 '11 at 15:24

A solution with matrix (version 2)

\input tikz
\usetikzlibrary{arrows,calc,matrix,decorations.pathreplacing}
\parindent=0pt
\tikzpicture[
b/.style={
text width=3.2cm,,minimum height=0pt,,minimum width=0pt
inner sep =.2cm,anchor=north west,
align=left},
m/.style={matrix of nodes,
inner sep=2pt,
outer sep=0pt,
column sep=0pt,
draw=black!50},
nodes={minimum height=2cm,
minimum width=3.6cm}]
\matrix[m] (M) {%
{} & {} \\
{}&  {}\\
};

\node[b] at (M-1-1.north west){%
Hey, this is a node with a break\break and stuff };
\node[b] at (M-1-2.north west){%
And another one with it. Milkshakes are yummy when the sun is shining};
\node[b] at (M-2-1.north west){%
Let's see what happens; I'm trying to find the logic };
\node[b] at (M-2-2.north west){%
Does it break when all these cells have different amount of text?};

\draw[very thick,red!50] (M-1-1.north east)--(M-2-1.south east)
(M-1-1.south west)--(M-2-2.north east);
\draw[double,green!50!black] (M-1-1.north west) rectangle (M-2-2.south east);
\draw[decorate,decoration={brace,mirror,raise=6pt}]%
(M-1-1.north west)--(M-2-1.south west);
\node[anchor=east,left=1em] at (M-1-1.south west){%
I'd like for the cells to be top-aligned};
\node[anchor=west] at (M-1-2.south east) {Yes it does};
\endtikzpicture
\bye


-
With pdflatex the solution that I use here tex.stackexchange.com/questions/20491/help-with-figures-in-tikz works very well. – Alain Matthes Jun 12 '11 at 17:14
Thanks for the answer. Although, I was looking for a solution using \matrix[matrix of nodes] – morbusg Jun 12 '11 at 18:41
@morbusg If you want a matrix you can look at the version 2 – Alain Matthes Jun 12 '11 at 22:00

You need to make a couple of changes to the above. There is probably more than one way to do this, but the following gives me a reasonable picture. Whether or not it is the best solution for you depends on what else you are trying to do here. To understand it, you need to realise that there are several layers involved. There's the placement of the text in the node box, the placement of the node in its matrix cell, and the alignment of the matrix cells. Your styles are trying to act on all of these and causing conflicts. What I've done in the following is to simplify this by taking the size stuff out of the nodes and put it in to the matrix.

The basic problem is that you can't have full control over how text is positioned within a node. The node is meant to be just big enough to contain the text and to grow accordingly. You can override its automatic size calculations, but only by specifying absolutes. The text is always placed at the centre of the node. The only way to override that is to tell TikZ/TeX that the text is not quite what it thinks it is - this is what the text height and text depth keys are for. But if you want to tell TikZ the exact height and depth (as you don't in this example since it changes for each node), then when you specify the minimum size it grows the node in all directions so as to keep the text at the centre.

So when doing complicated positioning like this, it is best to not mess with the nodes too much and let the matrix do the alignment. Thus anchor=north puts each node's anchor at the alignment point, but that only works if the text is flushed to the top of the node, and that only works if the node is the right size for its text. Hence my suggestion (in the comments) of anchor=north didn't work because you were trying to be too clever with the node dimensions.

So we let the nodes be their natural size and pass control of the cell size to the matrix. We do this by using the row sep key, with the between origins to make it look as if each cell was the same height.

This does mess up the sizes of the nodes, but to fix that you could use my matrixcells package (available from the TeX-SX package, see the "From Answers to Packages" for more details). Disclaimer: I've no idea if it works with plain TeX. If you know the exact sizes the nodes should be then you don't need to use that package (it would be overkill). What you need to do in that case is to ensure that TikZ/TeX sees the text as a box of the right dimensions (in this case 3.5cm square) and position the text within that box how you want. In LaTeX I'd use a minipage or parbox for this, I don't know how to do it in plain TeX.

\input tikz
\usetikzlibrary{matrix}
\hbox{I'd like for the cells to be top-aligned}\cases{ \tikzpicture[ a/.style={draw=green!50!black,text width=3.5cm, anchor=north, inner sep=0pt,outer sep=0pt}, m/.style={matrix of nodes,inner sep=2pt,outer sep=0pt,nodes=a, ampersand replacement=\&,row sep={3.5cm,between origins},column sep=0pt,draw=black!50} ] \parindent0pt \matrix[m] (mx) { Hey, this is a node with a break\break and stuff\& And another one with it. Milkshakes are yummy when the sun is shining\\ Let's see what happens; I'm trying to find the logic\& Does it break when all these cells have different amount of text?\\ }; \draw[very thick,red!50] (mx.north)--(mx.south) (mx.west)--(mx.east); \endtikzpicture } \hbox{Yes it does}
\bye


Result:

-
Thanks for the answer. Although, I need to have each node with the same height (because they will be getting a background-color, and look funky if they have different height---that's why I included the border color here). – morbusg Jun 12 '11 at 16:00
@morbusg: I suspected that might be the case (though it might have been that they were in to highlight the problem ...). That's why I suggested my matrixcells package. That draws a new node which is the size of the matrix cell as seen from the outside, so it can be filled or styled accordingly without needing this. However, if you know in advance that everything will be the same height you don't need to use that package ... wait a bit and I'll modify my answer. – Loop Space Jun 12 '11 at 16:06
@morbusg: Actually, I don't think that I can modify my answer to fix this problem, but maybe I can modify it so that you can. I know how I would fix it in LaTeX but don't know anything about plain TeX. – Loop Space Jun 12 '11 at 16:10
@morbusg: edited. I hope that's enough clues! – Loop Space Jun 12 '11 at 16:16
"The text is always placed at the centre of the node." This was the vital piece of information I was missing. +1 Thanks! It's a weird restriction, IMO, since I'm basically asking for a \vtop to 3.5cm. – morbusg Jun 12 '11 at 16:27

Oh gosh, I even said it out loud myself in a comment, without even realizing it could indeed be used inside a node:

\input tikz
\usetikzlibrary{matrix}
\tikzpicture
\parindent0pt
\matrix[matrix of nodes, inner sep=.5cm, nodes={text width=3cm}] (mx) {
|[fill=green!10]|\vtop to 3cm{
Hey, this is a node with a break\hfil\break and stuff\vfil}&
|[fill=red!10]|\vtop to 3cm{
And another one with it. Milkshakes are yummy when the sun is shining\vfil}\\
|[fill=blue!10]|\vtop to 3cm{
Let's see what happens; I'm trying to find the logic\vfil}&
|[fill=yellow!10]|\vtop to 3cm{
Does it break when all these cells have different amount of text?\vfil}\\
};
\draw[very thick,red!50] (mx.north)--(mx.south) (mx.west)--(mx.east);
\endtikzpicture
\bye

-