# TikZ line thickness seems to inappropriately affect label position

The following code produces two parallel vertical lines of the same length, but of different thicknesses, with labels at the top.

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw (0pt,0pt)
to +(0pt,10pt) node [above] {x};
\draw [ultra thick, red] (2pt,0pt)
to +(0pt,10pt) node [above] {x};
\end{tikzpicture}
\end{document}


Here's the output:

The problem is that the labels at the top are put in different heights, even though the lines are exactly the same length.

A trivial fix would be to adjust the label placement carefully for each line. But I have lots of labels at the top of vertical lines like this, and several of my lines have different thicknesses -- I really want to correct placement to be automatic.

-
I am guessing that for the label placement 0.5\pgflinewidth is added (and maybe even some additional stuff). I would normally expect that only to happen when a cap is used though... After some experimentation it turns out the extra space is added regardless of the line cap that is used. –  Roelof Spijker Jan 12 '12 at 12:15

This is because the line width is used in the computation of the anchors of the node, even if the line is not drawn. So the actual size of the node is node width + line width. This makes sense, at least for drawn nodes, as if you said \draw[->] (a) -- (b); then you would want the arrow to touch the edge of the box around (b), not to end in the middle of the line. Admittedly, one can debate whether or not this makes sense if the node is not stroked, but given that it is easier to turn this off than on, I would favour the current behaviour.

To make node sizes consistent, therefore, one simply has to ensure that the line width is consistent. This has to be done on the node so as not to interfere with the rest of the picture. One could simply put every node/.style={thick} at the start. This would then be overridden by any per-node options, which is what you would want. Depending on the actual desired outcome, there are various other ways one could do this. If you have nodes that are drawn (and so where the line thickness matters) with differing line thicknesses but you want them all aligned correctly, then one would have to adjust the positioning a little, but as it would always be by .5\pgflinewidth this would not be that difficult - the main issue would be ensuring that the adjustment is done at the right time, so that the correct line width is used.

Here's a little diagram showing all of the above:

Here's the code to reproduce that in case it's not clear:

\documentclass{standalone}
%\url{http://tex.stackexchange.com/q/40871/86}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[scale=4]
\node[ultra thick,draw] (a) at (0,0) {};
\node[ultra thick,draw] (b) at (0,1) {};
\draw[red,->] (a) -- (b);
\begin{scope}[xshift = 1cm]
\node[ultra thick,draw] (a) at (0,0) {};
\node[] (b) at (0,1) {};
\node[ultra thick,draw] at (b) {};
\draw[red,->] (a) -- (b);
\begin{scope}[xshift = 1cm]
\draw (0pt,0pt)
to +(0pt,10pt) node [above] {x};
\draw [ultra thick, red] (2pt,0pt)
to +(0pt,10pt) node [above] {x};
\begin{scope}[xshift = 1cm]
\draw (0pt,0pt)
to +(0pt,10pt) node [draw,above] {x};
\draw [ultra thick, red] (2pt,0pt)
to +(0pt,10pt) node [draw,above] {x};
\begin{scope}[xshift = 1cm]
\draw (0pt,0pt)
to +(0pt,10pt) node [line width=0pt,above] {x};
\draw [ultra thick, red] (2pt,0pt)
to +(0pt,10pt) node [line width=0pt,above] {x};
\end{scope}
\end{scope}
\end{scope}
\end{scope}
\end{tikzpicture}
\end{document}

-
Stunningly clear as always, thanks Andrew. –  Jamie Vicary Jan 12 '12 at 12:15
Alternatively you could used above=-.5\pgflinewidth. You could wrap it up in a style that takes an argument such that you could still give an optional extra argument to it. –  Roelof Spijker Jan 12 '12 at 12:22
@wh1t3 That's the sort of thing I was thinking about at the end of the second paragraph, except that I was lazy and didn't even think of one way to implement it! It would need a little testing to be sure that the right \pgflinewidth was being used. An alternative would be to define a node that was definitely not drawn and whose side did not depend on the line width. Knowing what was the best implementation would depend a bit on knowing the circumstances where it was going to be used. –  Loop Space Jan 12 '12 at 12:30
@AndrewStacey: You are worried that \pgflinewidth might expand at a time when it is not equal to the node's line width? I'm not familiar enough with the internals to say with 100% confidence that that will never happen, I seriously doubt it will though. Defining an extra node should work in all cases, but it does introduce an extra node each time. I agree that it would depend on the usecase which is best. –  Roelof Spijker Jan 12 '12 at 12:41
Mea culpa: I meant node shape. As for when \pgflinewidth is expanded, it would depend a bit on when everything happened. I got into a terrible mess early on in my days here because I wanted to allow three options to be specified in an arbitrary order, but two of them depended on the third so they had to work in a confused "wait until the third is given and then do this" manner. Some options are processed when they are given, some are stored until later, and without investigating I'm always hesitant at assuming. –  Loop Space Jan 12 '12 at 12:58