Graphviz Layout: Node Spacing, Rank Spacing, and Direction
This article is for people who are already familiar with Graphviz and want more control over the layout of a DOT diagram.
With the dot engine, set nodesep for the minimum space between nodes on the same rank and ranksep for the minimum space between ranks. rankdir=TB puts successive ranks below each other; rankdir=LR puts them to the right. These are layout requests, not fixed center-to-center distances.
Below are a few layout options for a small service diagram. For a focused example of putting nodes on the same rank, see how to align Graphviz nodes.
That would be our starting point, let's say we are creating a simple system architecture diagram.
digraph Graph {
node[shape=rect]
gateway -> users
gateway -> companies
gateway -> groups
}
specify Width and Heigh of nodes
explicitly set width and height of nodes
digraph Graph {
node[shape=rect]
gateway[width=3 height=0.3]
gateway -> users
gateway -> companies
gateway -> groups
}
splines - change arrow line shapes
digraph Graph {
node[shape=rect]
splines=ortho
gateway[width=3 height=0.3]
gateway -> users
gateway -> companies
gateway -> groups
}
Compare node and rank spacing with the same graph
In dot, both nodesep and ranksep are specified in inches. Defaults are nodesep=0.25 and ranksep=0.5. nodesep is the minimum gap between neighbors on one rank; ranksep is the minimum gap between ranks. Labels and other layout constraints can make the actual gaps larger.
Start with top-to-bottom (TB) flow, leaving both spacing values at their defaults:
digraph Service {
graph [rankdir=TB];
node [shape=box];
request -> api;
request -> worker;
api -> store;
worker -> store;
}
Open the default TB diagram in the playground
Now keep every node and edge but set nodesep=0.85 and ranksep=1.2:
digraph Service {
graph [rankdir=TB, nodesep=0.85, ranksep=1.2];
node [shape=box];
request -> api;
request -> worker;
api -> store;
worker -> store;
}
Open the spaced TB diagram in the playground
In this four-node render, the API-to-Worker center distance grows from 73 to 116 points, and the Request-to-API rank distance grows from 72 to 122 points. Those measured distances describe this diagram, not a conversion rule from the attribute values: node sizes and routing affect the final geometry.
Rotate the same spaced graph from TB to LR
Change only rankdir to LR:
digraph Service {
graph [rankdir=LR, nodesep=0.85, ranksep=1.2];
node [shape=box];
request -> api;
request -> worker;
api -> store;
worker -> store;
}
Open the spaced LR diagram in the playground
With TB, ranksep separates rows vertically and nodesep separates nodes across each row. With LR, ranksep separates columns horizontally and nodesep separates nodes vertically within a column. This comparison uses the site's Graphviz dot renderer; other engines such as neato do not follow the same rank rules. See the Graphviz nodesep and ranksep references for the full attribute behavior.
Now let's say I add one more edge, and it changes the weights of nodes and makes graph looks like that
digraph Graph {
node[shape=rect]
splines=ortho
gateway[width=3 height=0.3]
gateway -> users
users -> companies
gateway -> companies
gateway -> groups
nodesep=1
}
there are 2 ways to address that
apply rank to subgraph items
you can apply same 'rank' to a subgraph
digraph Graph {
node[shape=rect]
splines=ortho
gateway[width=3 height=0.3]
gateway -> users
users -> companies
gateway -> companies
gateway -> groups
nodesep=1
{
rank=same
users
companies
}
}
constraint
if you see that some arrow adds to much weight to a node, you can exclude it from ranking
digraph Graph {
node[shape=rect]
splines=ortho
gateway[width=3 height=0.3]
gateway -> users
users -> companies[constraint=false]
gateway -> companies
gateway -> groups
nodesep=1
}
Please checkout some of our useful resources:
- Graphviz cheatsheet
- Graphviz Playground
- Graphviz interactive tutorial
- Graphviz vs MermaidJS comparison
- Align Graphviz nodes on the same rank
This article was originally published in DevToolsDaily blog
