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.

JavaScript D3 Examples
← All posts
Organization Chart JavaScript

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.

Latest posts

All posts

Cytoscape JS Examples

Cytoscape JS examples are node-link graphs, not bar charts. Here are four I actually paste: force, hierarchy, circle, and tap to highlight.

Cytoscape Examples Networks
Read post