Home/ Cookbook/ Charts/ Treemap

Treemap by area

Nested rectangles whose areas encode share of a total. The chart that turns "where is the budget going?" into a single, scannable picture — even when there are 30 categories.

Charts · 17 of 20 1 primitive · Chart.Treemap ~15 min React · @corelithzw/react

Overview

Each rectangle's area is its proportion of the whole. Rectangles tile a fixed canvas, so the chart never needs an axis.

A treemap solves the problem pie charts can't: hierarchies with too many slices. Where a pie melts beyond five wedges, a treemap stays legible at 50 — the eye reads rectangle area very accurately, and labels sit inside the largest cells without overflow. The hierarchy is built in: parent rectangles contain child rectangles, so "Operations / Salaries / Senior" is one drill-down away.

Reach for it when you have a flat or shallow hierarchy of 10–100 leaves and the question is composition — budget by department, sales by SKU, time logged by project. Skip it for small hierarchies (use a stacked bar) and for time series (always a line). Avoid it when categories are similar in size — the rectangles collapse to a uniform grid and the visual story dies.

The opinion: always label the four or five biggest rectangles inline; smaller ones get a tooltip and a row in the legend. Hover-only labels make the chart feel like a riddle.

The chart

Operating expenses for the quarter, by department. Salaries dominate; rent and utilities form a band; everything else is the long tail.

Q3 opex by department Salaries 48%, rent 14%, utilities 9%, marketing 8%, supplies 7%, software 6%, travel 4%, professional fees 2%, other 2%. Salaries $ 482k · 48% Rent $ 140k · 14% Utilities $ 90k · 9% Marketing $ 80k · 8% Supplies $ 70k · 7% Software $ 60k · 6% Travel $ 40k · 4% Other · $ 20k

Required pieces

Roadmap: Chart.Treemap uses squarified-tile layout in v0.2. v0.1-alpha users compute coordinates server-side using d3-hierarchy equivalents and emit <rect>s.

React snippet

Pass a nested tree of {label, value, children?}.

Chart.Treemap@corelithzw/react

Customising

Drill-down on click

Tap a rectangle to zoom into its children. Use for two-level hierarchies — department → cost centre.

<Chart.Treemap
  data={opex}
  onDrillDown={(node) =>
    setFocus(node.label)
  }
  showBreadcrumb
/>

Diverging colour

Use a red-to-green scale when the colour represents change vs. prior period, not absolute value.

<Chart.Treemap
  data={opex}
  colorAccessor="deltaPct"
  colorScale="diverging"
  midpoint={0}
/>

Sub-grouped (two-level)

Show parent boundaries with a thicker stroke so the hierarchy reads at a glance.

<Chart.Treemap
  data={nested}
  parentStroke="var(--ink)"
  parentStrokeWidth={2}
  showParentLabels
/>

In context

Inside a "Spend overview" stat hero — the total leads, the treemap shows where it goes, a top-3 legend repeats the biggest items as text.

Q3 operating spend
$ 1.00M
Salaries $ 482k · 48% Rent · $140k Utilities · $90k Marketing Supplies · $70k Software · $60k Travel · $40k Other · $40k
Top categories
Salaries48%
Rent14%
Utilities9%
Marketing8%
Other21%

Accessibility

A treemap is hard to parse non-visually because the rectangles' layout is computed. The fallback is a sorted table.

  • One role="img" per treemap. The <title> names the chart; the <desc> lists categories sorted by share.
  • Aria-label states the headline share. "Operating expenses by department, salaries 48% of total" — the dominant rectangle gets the spoken summary.
  • Inline labels for big rectangles, table for small ones. Anything taking less than 5% of canvas area gets a tooltip — but every value is in the fallback table.
  • Hidden table is sorted by value descending. Screen-reader users read in importance order, not layout order.
  • Rectangles are tab targets. Each has an aria-label with name and exact share; arrow keys move between adjacent rectangles in reading order.
  • Drill-down has a breadcrumb. If the user can zoom in, the breadcrumb reads "Q3 opex · Salaries · Senior engineers" so they always know where they are.