Orientation and Circular Links
Two layout capabilities that change what a Sankey can represent: flowing the diagram top to bottom, and closing a loop back to an earlier rank.
Vertical orientation
const sankey = new ApexSankey(document.getElementById('chart'), {
orientation: 'vertical',
})
sankey.render(data)
orientation | Ranks | Flow direction |
|---|---|---|
'horizontal' (default) | Columns | Left to right |
'vertical' | Rows | Top to bottom |
Vertical is usually the better choice when:
- Category labels are long. Horizontal ranks force labels to compete for column width; rows give each label the full canvas width.
- The container is narrow. A phone-width viewport or a narrow dashboard column fits a vertical diagram far better.
- The metaphor is descent. Funnels, waterfalls and drilldowns read naturally downward.
Everything else is unchanged: the same data, the same options, the same interaction. axisTitles moves from above each column to beside each row. See Alluvial Diagrams.
Sizing
With height: 'auto' the canvas is derived from the width at a 1.6:1 ratio, which suits a horizontal diagram. A vertical diagram with several ranks usually wants explicit height instead:
const sankey = new ApexSankey(el, {
orientation: 'vertical',
width: 600,
height: 900,
})
Circular and cyclic links
A strict Sankey is acyclic: flow moves forward through ranks and never returns. Real systems are not always acyclic. Recycling returns material to production, a support queue reopens a ticket, an economy feeds output back as input.
ApexSankey routes those flows rather than rejecting them. An edge that points back to an earlier rank is drawn as a dashed back-edge, routed around the diagram body so it stays legible instead of cutting through the forward flows:
const data = {
nodes: [
{ id: 'raw', title: 'Raw material' },
{ id: 'product', title: 'Product' },
{ id: 'use', title: 'In use' },
{ id: 'recycle', title: 'Recycling' },
],
edges: [
{ source: 'raw', target: 'product', value: 100, type: 'flow' },
{ source: 'product', target: 'use', value: 100, type: 'flow' },
{ source: 'use', target: 'recycle', value: 40, type: 'flow' },
// the cycle: back to an earlier rank
{ source: 'recycle', target: 'raw', value: 35, type: 'loop' },
],
}
sankey.render(data)
No option is needed. A cycle is detected from the topology and rendered accordingly.
The dashed styling is deliberate: a back-edge is not the same kind of statement as a forward flow, and drawing it identically would imply a rank ordering that does not exist. Giving cyclic edges their own type (as above) also lets you style or filter them in tooltips.
Interaction with cycles
Path highlighting and click-to-focus are cycle-guarded, so following a flow around a loop terminates instead of walking forever. The same guard applies to the pathTrace plugin. See Path Highlighting and Interaction and Plugins and Events.
Combining the two
Orientation and cycles are independent, so a vertical diagram routes back-edges the same way:
const sankey = new ApexSankey(el, {
orientation: 'vertical',
height: 800,
theme: 'mint',
})
sankey.render(circularEconomyData)
For a system where the loop is the subject and there are no meaningful ranks at all, consider a chord diagram instead.