It is easy to produce a path between two nodes consisting of a single horizontal and a single vertical line (from the manual):

  \draw (0,0) node(a) [draw] {A}  (1,1) node(b) [draw] {B};
  \draw (a.north) |- (b.west);
  \draw[color=red] (a.east) -| (2,1.5) -| (b.north);

However, what if I wanted the same short syntax to produce a path between (a) and (b) using a horizontal line, a vertical line, and a second horizontal line. It isn't to difficult to calculate the intermediate points, but how could the following syntax be defined?

  \draw (0,0) node(a) [draw] {A}  (3,1) node(b) [draw] {B};
  \draw (a.east) -|- (b.west);
  • 1
    Do you mean something like \begin{tikzpicture} \draw (0,0) node(a) [draw] {A} (3,1) node(b) [draw] {B}; \draw (a.east) -- ++(1,0) |- (b.west); \end{tikzpicture}
    – percusse
    Feb 21, 2012 at 23:48

4 Answers 4


This answer extends Marc van Dongen's anwser.

The two styles are -|- and |-| with default value 0.5 to position the intermediate point (so, default is middle point).

enter image description here

    to path={
      (\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)
    to path={
      (\tikztostart) |- ($(\tikztostart)!#1!(\tikztotarget)$) -| (\tikztotarget)
  \draw[->,blue] (2.1,1.1) to[|-|] (1.1,0.1);
  \draw[->] (2,1) to[-|-] (1,0);

  \draw[->,blue] (3.1,0.1) to[|-|] (4.1,1.1);
  \draw[->] (3,0) to[-|-] (4,1);

    \draw[->,red] (2.1,1.1) to[|-|=.2] (1.1,0.1);
    \draw[->,orange] (2,1) to[-|-=.2] (1,0);

    \draw[->,red] (3.1,0.1) to[|-|=.8] (4.1,1.1);
    \draw[->,orange] (3,0) to[-|-=.8] (4,1);
  • 1
    Well, I must say: This pretty much want I wanted. Nice, touch to allow for something other than 0.5 i.e. the middle point. Simple syntax, didn't know that this was possible. Good answer!
    – DrJay
    Dec 11, 2012 at 18:02
  • Works perfect with the trees library using edge from parent path={(\tikzparentnode) to[|-|] (\tikzchildnode)}.
    – n4pK
    Jan 21, 2020 at 15:05

With my paths.ortho library that contains of

this is possible.

This works by re-writing and intercepting the main TikZ parser. (Which is also the reason this may break with an TikZ update.)

This library introduces six path operators:

  • in the hvvh family:
    • |-| and
    • -|-;
  • in the udlr family:
    • r-ud,
    • r-du,
    • r-lr and
    • r-rl.

For the hvvh family exist the following keys:

  • hvvh/spacing=<n>,

    • hvvh/middle 0 to 1 and hvvh/0 to 1 which are a short-cut (?) for hvvh/spacing=0

    This key affects the timer (that is the function that places nodes along the path).
    The two kinks on the path are the positions 1/<n> and (<n>-1)/<n>. (With |- and -| the kink is at .5.)

    The default is <n> = 4.

    If <n> = 0 (see also the middle 0 to 1 key above), then a special timer is installed that makes the kinks at pos=0 and pos=1. The start of the three-parted line is pos=-1 and the end is pos=2 then.

    The position .5 is always in the middle of the second part of the path.

    These timer settings are valid for the udlr family, too!

  • hvvh/ratio sets the ratio of the middle part in relation to the start and the end. Its default is .5. The values 0 and 1 will result in the well-known |- and -| paths.

  • hvvh/distance sets—similar to the ratio—the distance between the start and the middle. If this distance is set greater then the orthogonal distance of the to-be-connected coordinates (or less then zero), you will end up with something that also could have been produced with one of the udlr paths.

The udlr family is explained on my answer to How to draw a return arrow from node-3 to node-1.

Negative distances will result in paths that resemble the |-|/-|- paths.

Code (Question)

\begin{tikzpicture}[thick, ->]
  \draw[blue] (2.1,1.1) |-| (1.1,0.1);
  \draw       (2,1)     -|- (1,0);

  \draw[blue] (3.1,0.1) |-| (4.1,1.1);
  \draw       (3,0)     -|- (4,1);

  \begin{scope}[yshift=-1.5cm, hvvh/ratio=.2]
    \draw[red]    (2.1,1.1) |-| (1.1,0.1);
    \draw[orange] (2,1) -|- (1,0);

    \draw[red] (3.1,0.1) [hvvh/ratio=.8] |-| (4.1,1.1);
    \draw[orange, hvvh/ratio=.8]   (3,0) -|- (4,1);

Output (Question)

enter image description here

Examples of the usages of this library …

… can be found in paths.ortho-hvvh.tex and paths.ortho-udlr.tex. Animations created from these examples are hidden behind the following links:

  • 6
    This is just excellent, something I have missed for years drawing complex diagrams with TikZ. Have you considered trying to get this into the TikZ CVS (so that it will continue to work with future updates of TikZ)? Till Tantau hasn't been seen at tex.se so far, but Mark Wilbrow and Christian Feuersänger are both around and may be willing to help you in this respect.
    – Daniel
    Jun 6, 2013 at 8:53
  • 5
    I also think this should go in to the CVS. Tikz-uml has also a similar construction but this is way cleaner. However a minor problem is that it has to be freed from the etoolbox-related content. TikZ developers are very careful about that.
    – percusse
    Jun 6, 2013 at 12:33
  • @percusse That’s not a problem. The original draft didn’t used etoolbox but just re-defined the needed parsing macros. The \patchcmd version makes it a little bit more compatible if TikZ changes. But if it would be implemented there will be no re-definition but just one (ever-growing?) handler. But the code is still not complete or bug-free. For once I wanted to implement a switch that calculates the distances/ratios from the center of the nodes. Also the border is not always the correct one for certain values and combinations. (But that also happens with |-/-|.) Jun 6, 2013 at 12:56
  • 1
    Please consider making this more generally available before TikZ is dead and buried. I appreciate you may (still?) want to improve the code, but if you've not got around to it in 2.5 years, you probably aren't going to do so any time soon. Meanwhile, the code essentially sits on a shelf. If you contribute it, other people may help by sending you patches. If you include a TO DO, people will know the direction you'd like to go in. Perfection is a worthy aim, but so is availability. Pleeeeaaaase. I know how tempting it is to want to wait, tweak... but....
    – cfr
    Feb 15, 2016 at 23:38
  • 1
    I'd like to see it on CTAN. It really won't get generally used or be generally available otherwise. & I don't fear TikZ will die.
    – cfr
    May 14, 2016 at 20:46

You can do this with a to path. The following solution is intended to highlight the steps that are needed. The solution can draw connections in any direction, not just vertical/horizontal connections, and therefore generalises all other solutions presented thus far.

Also note the solution doesn't include an animated picture, so you can focus on the provided output without any risk of being distracted by the animation:-).

The solution shows a nice application of the not-too-frequently used projection modifier ($(a)!(b)!(c)$), which projects the point (b) onto the infinite line through (a) and (c).

The reader may add their own favourite auxiliary keys for drawing a horizontal-vertical-horizontal connection, or a vertical-horizontal-vertical connection.


% The parsing is done relative to the key "/my connection/,
% which is not part of the user-defined API
\pgfkeys{/my connection/.cd,
         % Save the angle value.
         angle/.store in=\mycon@angle,
         % Save the ratio value.
         ratio/.store in=\mycon@ratio,
         % The draw key triggers the drawing. Should be last.
         draw/.style={/tikz/to path={
         let % \n{a} is the angle.
             % \n{r} is the ratio.
             % \p{s} is the start of the connection.
             % \p{t} is the target of the connection.
             % \p{sa} is some point on the line from \p{s} in direction \n{a}.
             % \p{st} is some point on the line from \p{t} in direction \n{a}.
             % \p{proj s} is the projection of \p{s} on the line through \p{t} and \p{st}.
             \p{proj s}=($(\p{t})!(\p{s})!(\p{st})$),
             % \p{proj t} is the projection of \p{t} on the line through \p{s} and \p{sa}.
             \p{proj t}=($(\p{s})!(\p{t})!(\p{sa})$)
         in    % Second point of connection.
               -- ($(\p{s})!\n{r}!(\p{proj t})$)
               % Third point of connection.
               -- ($(\p{proj s})!\n{r}!(\p{t})$)
               % Last point of connection.
               -- (\p{t})
% The "connection" key is part of the user-defined API key.
% It has two sub-keys: ratio and angle, with default values 0.5
% and 0 respectively. We use the connection key to set the defaults,
% override the user-provided values for the keys (if any), and then
% draw the connection.
\tikzset{connection/.style={/my connection/.cd,ratio=0.5,angle=0,#1,draw}}


\draw (0,0) coordinate(a) node[anchor=north]{$a$}
      (6,3) coordinate(b) node[anchor=south]{$b$};
\draw[->]      (a) to[connection] (b);
\draw[blue,->] (b) to[connection={ratio=0.25,angle=30}] (a);
\draw[red,->]  (a) to[connection={ratio=0.25,angle=90}] (b);

sloped connections

  • Yes, I could do that. As stated it is easy to calculate the intermediate points (or point). But the question was wether it is possible to define the syntax: -|-
    – DrJay
    Feb 22, 2012 at 0:16
  • @MarcvanDongen I suggest some addition in my community answer... Dec 10, 2012 at 15:00
  • Allow me some criticism: All solutions with a to path are only able to place the nodes on one part of the whole zig-zag line (here: the last one) without further modification. This is one of the major reason why I created the library in the first place; the other one is that these kind of questions had come up once a week—I’m exaggerating, of course—when I created the udlr part. Jun 6, 2013 at 5:31
  • @MarcvanDongen You can only place a node between the last kink and the target: \draw (a) to[connection] node[pos=0] {0} node[pos=1] {1} (b); For the other solutions \tikztonodes need to be placed after first or the second kink. This means that one needs either three distinctive to paths or another solution (say a key part or an improved version of pos) to be able to place nodes at all parts of the line. Jun 6, 2013 at 6:38
  • @Qrrbrbirlbel If I understand you correctly, you're saying that it should be possible to treat the connection path as a whole so it's possible to compute points along the path. If not, please explain further. Otherwise, where does the OP make this request?
    – user10274
    Jun 6, 2013 at 9:08

Try this:

\path (0,0) node(a) [draw] {A} -- (3,1) node(b) [draw] {B} coordinate[pos=0.5](inter);
\draw (a) -| (inter) |- (b) ;
  • Hi, I get your point, but it does not answer the question!
    – DrJay
    Sep 11, 2014 at 22:50

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.