I'm using chains library from TikZ.
I would like to have a label(node?) above arrows. Is it possible?

I found this, but it is quite hackish.
Is there a standardized way?


I also needed labeled edges for TikZ chains, but needed to retain the features of the original join=with <node> by <options> syntax. So, I wrote some code to admit the syntax join=with <node> by <options> nodes <node path>. Here is that code, along with an example:



    \tikz@lib@join@by@nodes by {} nodes \pgfutil@stop%
    \pgfutil@in@{nodes }{#1}%
      \tikz@lib@parse@join@nodes#1 nodes \pgfutil@stop%

\def\tikz@lib@parse@join@nodes#1nodes #2\pgfutil@stop{%
  \pgfutil@in@{by }{#1}%
    \tikz@lib@parse@join@by#1nodes #2\pgfutil@stop%
    \tikz@lib@parse@join@by#1by {} nodes #2\pgfutil@stop%

\def\tikz@lib@parse@join@by#1by #2 nodes #3\pgfutil@stop{%
  \pgfutil@in@{with }{#1}%
    \tikz@lib@join@with@by@nodes#1by #2 nodes #3\pgfutil@stop%
    \tikz@lib@join@by@nodes by #2 nodes #3\pgfutil@stop%

\def\tikz@lib@join@with@by@nodes with #1 by #2 nodes #3\pgfutil@stop{%
  \tikzset{after node path={(#1)edge[every join,#2]#3(\tikzchaincurrent)}}%

\def\tikz@lib@join@by@nodes by #1 nodes #2\pgfutil@stop{%
  \tikzset{after node path={%
               (\tikzchainprevious)edge[every join,#1]#2(\tikzchaincurrent)%


\begin{tikzpicture}[start chain, every join/.append style={->}]
  \node [on chain, join] {A};

  \node [on chain, join] {B};

  \node [on chain, join=nodes {node [above] {$\gamma$}}] {C};

  \node [on chain=going below,
         join=by {red}  nodes {node [right] {$\delta$}}] {D};

  \node [continue chain=going left, on chain,
         join=with chain-begin by {<-, blue}
              nodes {node [sloped,above] {$\epsilon$}},
         join=with chain-2 by {|->, red}] {E};

  \node [on chain, join=by {<->,green},
                   join=with chain-begin] {F};

enter image description here


\tikz@lib@parse@join Macro

  1. \tikz@lib@parse@join first checks whether the argument to join is empty. If so, the join occurs with empty by and nodes components and no with component.

  2. Otherwise, we check whether there is a nodes component. If not, we append an empty nodes component to #1; the space inserted between #1 and nodes is needed because #1 (is not empty and) does not end with a space. We then call \tikz@lib@parse@join@nodes.

\tikz@lib@parse@join@nodes Macro

Now, thanks to the previous macro, a (possibly empty) nodes component is guaranteed to exist. We next check whether there is a by component. If not, we insert an empty by component. We then call \tikz@lib@parse@join@by.

Note that, in case we must insert an empty by, we do not add a space between #1 and by. This is because either:

  • there was only a nodes component, in which case #1 is empty; or
  • there was a with component in addition to the nodes component, in which case #1 contains the with and itself ends with a space.

\tikz@lib@parse@join@by Macro

Now, thanks to the previous macros, (possibly empty) by and nodes components are guaranteed to exist. We next check whether there is a with component. If so, we call \tikz@lib@join@with@by@nodes. Otherwise, we call \tikz@lib@join@by@nodes.

| improve this answer | |
  • I tried to use join=by {to path={|- (\tikztotarget)}} nodes {node[above]{a} but that did not work? Maybe you know why? – maetra Sep 23 '13 at 15:45

The page you link to isn't hackish. It's as simple and clean as it could be.

\chainin (m-2-3) [join={node[above] {$x$}}];

How much more straight forward could it get?

| improve this answer | |
  • 3
    "a workaround by modifying the join method of the chain library. Its syntax is join=with<node> by <options>, I’m changing the syntax to join={node[options] {label}}" - I understand that old syntax won't work anymore? – Łukasz Lew Jan 20 '11 at 4:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.