Tidy tree

structure

A tidy tree. The default for anything with one parent per node.

Tidy tree — structure: rendered example
Rendered by Gnomon from the source below. No edits.

The source

68 lines of D3 JavaScript, and uses only the bundled D3 build. Copy it, or open the template inside Gnomon and render it as it is.

// Tidy tree — Reingold–Tilford. The layout for an org chart, a decision
// tree, or any structure where depth means something.

const data = {
  name: 'Platform',
  children: [
    { name: 'Experience', children: [
      { name: 'Web' }, { name: 'Mobile' }, { name: 'Design system' },
    ]},
    { name: 'Domain', children: [
      { name: 'Orders', children: [{ name: 'Fulfilment' }, { name: 'Returns' }] },
      { name: 'Catalogue' },
      { name: 'Payments', children: [{ name: 'Ledger' }, { name: 'Payouts' }] },
    ]},
    { name: 'Platform', children: [
      { name: 'Data' }, { name: 'Infra' }, { name: 'Security' },
    ]},
  ],
};

const root = d3.hierarchy(data);
const dx = 26;
const dy = (width - 200) / (root.height + 1);
d3.tree().nodeSize([dx, dy])(root);

// Node coordinates come out centred on zero; measure the extent and set the
// viewBox from it rather than guessing a translate.
let x0 = Infinity;
let x1 = -Infinity;
root.each(d => {
  if (d.x > x1) x1 = d.x;
  if (d.x < x0) x0 = d.x;
});
const boxHeight = x1 - x0 + dx * 2;

const svg = d3.select(container).append('svg')
    .attr('viewBox', [-dy / 2, x0 - dx, width, boxHeight])
    .attr('width', width)
    .attr('height', boxHeight)
    .attr('font-family', 'system-ui, sans-serif')
    .attr('font-size', 11);

svg.append('g')
    .attr('fill', 'none')
    .attr('stroke', theme.muted)
    .attr('stroke-opacity', 0.5)
    .attr('stroke-width', 1.5)
  .selectAll('path')
  .data(root.links())
  .join('path')
    .attr('d', d3.linkHorizontal().x(d => d.y).y(d => d.x));

const node = svg.append('g')
  .selectAll('g')
  .data(root.descendants())
  .join('g')
    .attr('transform', d => `translate(${d.y},${d.x})`);

node.append('circle')
    .attr('r', 4)
    .attr('fill', d => d.children ? theme.accent : theme.palette[4]);

node.append('text')
    .attr('dy', '0.32em')
    .attr('x', d => d.children ? -8 : 8)
    .attr('text-anchor', d => d.children ? 'end' : 'start')
    .attr('fill', theme.foreground)
    .text(d => d.data.name);

Render this offline

This template ships in Gnomon and renders on your machine, with no account and nothing sent to a server. The browser editor is free and needs no install.

Get GnomonOpen the browser editor

Others in D3 visualisations