# How do I get arrows and nodes in my commutative diagrams to line up?

I use for typesetting my commutative diagrams. I generally use the matrix of math nodes which has the pleasant effect of ensuring that all of the entries in a row are aligned according to their baselines. Compare the two versions in the following picture, the left are aligned by their center [sic] anchors, the right by their base ones.

This works well, until one adds arrows. Unless given explicit anchors, arrows are drawn between the centres of nodes and whilst the bases of the right-hand nodes are aligned, their centres are not. So adding arrows yields the following:

Now, clearly I'm exaggerating for effect but it is noticeable even with a slight discrepancy.

One can manually add the anchors, but that's a pain (and the seemingly best anchor, mid, is ever so slightly too low: it is at .5ex above baseline but by examining $$A \to B$$ I think it should be at .6ex).

So my question: can I align both nodes and arrows so that the nodes are aligned by baseline but \draw[->] (a) -- (b); just works.

Here's some code to play with:

\documentclass{article}
\usepackage{tikz}

\begin{document}
\tikz[baseline]{ \node[rectangle] (a) {$$A_{\rule{1pt}{2em}}$$};
\node[rectangle] (b) at (2,0) {$$B^{\rule{1pt}{2em}}$$}; \draw[->] (a)
-- (b);}
\tikz[baseline]{ \node[anchor=base,rectangle] (a)
{$$A_{\rule{1pt}{2em}}$$}; \node[anchor=base,rectangle] (b) at (2,0)
{$$B^{\rule{1pt}{2em}}$$}; \draw[->] (a) -- (b);}
\end{document}


Note: This is an ask-and-answer question. I spent a not-insignificant amount of time hacking this this afternoon. Then I did a bit of searching to see if the question had already been asked, and while it hadn't - hence still asking - I did find that, to coin a phrase, "there's a package for that", but I didn't find the solution from that package mentioned anywhere on this site - though this problem has been seen in other answers.

-

The solution, as I found after not-quite-fruitless hacking, is provided by the tikz-cd package. Although I prefer doing my commutative diagrams "by hand", this package does still define some useful things that can be used without using its specific environment. In this particular case, the asymmetrical rectangle. This is a rectangular node which is such that its "center" is where the "mid" would be in a normal rectangular node, and thus the "center" is not actually at the centre of the surrounding box (as I learnt in my hacking, this makes it a little more complicated to compute the right boundary point, but not impossible).

(And the resulting arrow is at the right height.)

Witness:

Produced by:

\documentclass{article}
\usepackage{tikz}

\begin{document}
\tikz[baseline]{
\node[rectangle] (a) {$$A_{\rule{1pt}{2em}}$$};
\node[rectangle] (b) at (2,0) {$$B^{\rule{1pt}{2em}}$$};
\draw[->] (a) -- (b);}

\tikz[baseline]{
\node[anchor=base,rectangle] (a) {$$A_{\rule{1pt}{2em}}$$};
\node[anchor=base,rectangle] (b) at (2,0) {$$B^{\rule{1pt}{2em}}$$};
\draw[->] (a) -- (b);}

\tikz[baseline]{
\node[asymmetrical rectangle] (a) {$$A_{\rule{1pt}{2em}}$$};
\node[asymmetrical rectangle] (b) at (2,0) {$$B^{\rule{1pt}{2em}}$$};
\draw[-to] (a) -- (b);}

$$\tikz[baseline=(a.base),remember picture] \node[asymmetrical rectangle] (a) {\(A_{\rule{1pt}{2em}}$$};
A \to B
\tikz[baseline=(b.base),remember picture] \node[asymmetrical
rectangle] (b) at (2,0) {$$B^{\rule{1pt}{2em}}$$};
\tikz[overlay,remember picture] \draw[-to] (a) -- (b);
\)

\end{document}

-
A bit of nitpicking. Don't you need to include the package tikz-cd in your code? Furthermore, to produce the picture you give, you probably need to remove the empty lines in your code between the tikz picture environments. In any case, thank you very much for the reference to the asymmetrical rectangles from tikz-cd. –  Ricardo Andrade Sep 16 '12 at 0:08
@RicardoAndrade Nit-pick away! Don't know how the first slipped through. The second I'll not bother to change as I'd prefer to keep the code spaced out for clarity. It's never quite true when I say "was produced by" as I almost always use the standalone class but don't like to put that in the code example. –  Loop Space Sep 16 '12 at 7:02