Three treemap libraries, side by side

Same data, three renderers: Plotly.js, D3, and gp-treemap. Each section walks the same canonical hierarchy and translates it into whatever each library wants (labels/parents/values arrays for Plotly and gp-treemap; a nested object for D3). No re-walking, no separate data pipelines — just three different renderings.

Up front: we love Plotly. It's our go-to for everything else, and its treemap defaults are some of the nicest out of the box. This comparison is about scale, not quality.

1. A 24-row toy dataset

Coffee-shop sales by region → category → product. Tiny enough that every library renders comfortably; useful as a baseline for visual style and default behavior.

gp-treemap Ours canvasopen ↗
queued
Plotly.js treemapopen ↗
queued
D3 d3-hierarchy + SVGopen ↗
queued

What's different at this scale

The gp-treemap tradeoff: only nodes with their own pixel area get an explicit rect. Interior nodes (folders, categories) don't get a separate "container" rect or a top-strip label — their boundary is implied by the seam-and-shading between children. That means there's no parent rect to click on. Instead, gp-treemap surfaces parents through the breadcrumb at the bottom: hover or click any leaf and the full ancestor path lights up, with the stats bar showing each ancestor's aggregate. Click a breadcrumb segment to focus that ancestor; double-click to zoom to it. (Outside an iframe the mouse wheel also walks the focus up and down the ancestor chain — try the full-page versions linked above.)

Their tradeoff in return: every parent strip Plotly and D3 reserve for a label is pixels that came out of that parent's area. The children inside still fill the rectangle, but the rectangle itself is smaller than the parent's true share of the total. The distortion compounds with depth — at five levels of nesting, a leaf's visible area can be noticeably smaller than its proportional value. gp-treemap doesn't reserve gutters, so cell area is exactly proportional to leaf size all the way down.

2. Disk usage of this repo

17,561 files and folders, 321 MB total — including .git, which dominates by byte count. Same hierarchy in all three frames.

gp-treemap Ours canvasopen ↗
queued
Plotly.js treemapopen ↗
queued
D3 d3-hierarchy + SVGopen ↗
queued

Why the gap widens

3. A 137,262-node dataset

California city-government wages, 2024 (Government Compensation in California), rolled up by department → county → employer → position → individual row. 100,000 rows, 137,262 tree nodes — an order of magnitude bigger than the repo above.

gp-treemap Ours canvasopen ↗
queued
Plotly.js treemapopen ↗
queued
D3 d3-hierarchy + SVGopen ↗
queued

At this scale the divergence is dramatic: Plotly and D3 may take tens of seconds, freeze, or fail to load at all; gp-treemap renders the whole tree in well under a second.

Takeaways

Render times are measured live in your browser — each iframe reports back when its first paint completes. Regenerate everything with node scripts/build-comparison.mjs.