Organization Chart JavaScript
An organization chart in JavaScript is a tree of boxes, not a force graph. Here's d3.tree with elbows, a horizontal variant, and click to collapse.
An organization chart in JavaScript is a tree: one person at the top, reports arranged underneath, elbow-shaped connectors between the boxes. It's not a force graph, and it matters that it isn't. If you run a force layout on org data, the nodes bounce around and the hierarchy completely disappears — it ends up looking like a party rather than a reporting structure. I wrote Cytoscape JS examples for that network shape. This page is specifically the reporting-line shape.
Below: a vertical tree you can collapse by clicking, a left-to-right
variant, and the core d3.tree snippet. The names are made
up. The layout is the real thing. For the broader D3 API, see the D3.js page.
What an organization chart is
Nested data. Each node has a name, a role, and maybe children. The
layout's only job is: depth becomes y, siblings share a row, lines
don't cross if you can help it. That's d3.hierarchy plus
d3.tree.
A mind map is the same tree with fluffier boxes. A network graph is not: people can report in cycles in real life, but an org chart pretends they don't. Keep the data a tree or the layout will lie.
Vertical org chart
CEO at the top, elbows down. Click a manager to hide their reports.
Click again to open. Hidden reports get a + on the role.
That's children swapped onto _children, then
the tree runs again.
Preview
Click a box with reports to collapse it.
Horizontal org chart
Same tree, x and y swapped. I use this when names are long or the
page is wide and short. nodeSize is the knob: first
number is sibling spacing, second is rank spacing.
Preview
The code
The snippet is the core: hierarchy, tree, elbow path, labels. The live
charts also draw cards and collapse. Don't use d3.linkVertical
for an org chart. That's a diagonal. HR wants elbows.
Code
const data = {
name: "Maya Chen",
role: "CEO",
children: [
{ name: "Jordan Hale", role: "CTO", children: [{ name: "Priya Shah", role: "Eng" }] },
{ name: "Alex Ruiz", role: "CFO" },
],
};
const root = d3.hierarchy(data);
d3.tree().nodeSize([156, 108])(root);
const svg = d3.select("#chart").append("svg").attr("viewBox", "0 0 640 420");
const g = svg.append("g").attr("transform", "translate(320,40)");
g.selectAll("path")
.data(root.links())
.join("path")
.attr("fill", "none")
.attr("stroke", "#e8b84a")
.attr("d", (d) => {
const mid = (d.source.y + d.target.y) / 2;
return `M${d.source.x},${d.source.y} V${mid} H${d.target.x} V${d.target.y}`;
});
g.selectAll("g")
.data(root.descendants())
.join("g")
.attr("transform", (d) => `translate(${d.x},${d.y})`)
.append("text")
.attr("text-anchor", "middle")
.text((d) => d.data.name);
Which library I'd use
| If you need | I'd use |
|---|---|
| A picture of a reporting tree | D3 tree, like this page |
| Pan, tap, filter, a few hundred people | Cytoscape.js breadthfirst (examples) |
| The same in a vis-network canvas | vis.js hierarchical layout |
| Six boxes on a marketing page | SVG, no library (how) |
A force layout is the wrong default. That's D3 graph examples, and it's for networks. If the “org chart” is really money moving between teams, a sankey is clearer than boxes.
Questions I get
How do I make an organization chart in JavaScript?
Model your data as a tree — each person has a name, a role, and optionally an array of children. Pass that to d3.hierarchy, then run d3.tree on it to calculate x/y positions for each node. From there you draw rounded rects for boxes, elbow-shaped paths for the connector lines, and text for names and titles. Add a click handler that swaps children onto _children (and back) if you want collapse behavior.
What library should I use for an organization chart in JavaScript?
d3.tree is my go-to for a static org chart with elbow connectors — it's what this page uses. If you need something users can pan around, tap on nodes, and filter, Cytoscape.js with breadthfirst layout is the better fit. vis.js hierarchical layout is the third option I'd consider. Whatever you do, don't use a force-directed layout. Force layouts are for networks. They'll turn your reporting structure into a blob.
Can I make an organization chart without a library?
Yes, for a small tree. Recurse the data, calculate x and y yourself, draw SVG rectangles and lines. It's manageable for two levels. Once you have three or more levels with variable numbers of children, getting the sibling spacing right without d3.tree becomes a real project.
Org chart vs network graph?
An org chart is a strict tree: one parent per person, reporting lines go down. A network can have cycles, many-to-many connections, no root. The layouts are completely different. If you try to draw an org chart with a force-directed layout, it'll look like everyone showed up to the same party at once — no structure, no hierarchy visible.
How do I collapse nodes in a D3 org chart?
D3 doesn't handle collapse for you — you implement it manually. On click: if the node has children, move them to d._children and set d.children to null. If d._children exists, copy it back to d.children. Then re-run d3.tree and redraw. The + marker on collapsed nodes in the preview here is just a visual hint that reports are hidden — you add that in your render function by checking whether _children is non-null.