Basic Treemap — D3.js

A treemap displaying hierarchical data as nested rectangles, where each rectangle's area is proportional to its value. This visualization excels at showing part-to-whole relationships in hierarchical structures, making it easy to spot large and small items at a glance. Treemaps efficiently use screen space to display large amounts of hierarchical data in a compact form.

Basic Treemap rendered with D3.js

JavaScript source (D3.js)

// anyplot.ai
// treemap-basic: Basic Treemap
// Library: d3 7.9.0 | JavaScript 22.23.1
// Quality: 92/100 | Created: 2026-08-04

const t = window.ANYPLOT_TOKENS;
const { width, height } = window.ANYPLOT_SIZE;

// --- Data (in-memory, deterministic) ----------------------------------------
// R&D budget allocation ($ thousands) by division and project
const data = {
  name: "root",
  children: [
    {
      name: "Software Engineering",
      children: [
        { name: "Platform Core", value: 420 },
        { name: "Mobile Apps", value: 310 },
        { name: "DevOps Tooling", value: 180 },
        { name: "API Gateway", value: 140 },
      ],
    },
    {
      name: "Hardware Engineering",
      children: [
        { name: "Sensor R&D", value: 260 },
        { name: "PCB Design", value: 190 },
        { name: "Prototyping Lab", value: 150 },
      ],
    },
    {
      name: "Data Science",
      children: [
        { name: "ML Platform", value: 240 },
        { name: "Forecasting Models", value: 170 },
        { name: "Data Pipeline", value: 130 },
      ],
    },
    {
      name: "Product Design",
      children: [
        { name: "UX Research", value: 150 },
        { name: "Visual Design", value: 110 },
      ],
    },
    {
      name: "Quality Assurance",
      children: [
        { name: "Automated Testing", value: 160 },
        { name: "Manual QA", value: 90 },
      ],
    },
  ],
};

const divisions = data.children.map((d) => d.name);
const color = d3.scaleOrdinal().domain(divisions).range(t.palette);

// --- Layout -------------------------------------------------------------------
const margin = { top: 130, right: 40, bottom: 40, left: 40 };
const iw = width - margin.left - margin.right;
const ih = height - margin.top - margin.bottom;

const root = d3
  .hierarchy(data)
  .sum((d) => d.value)
  .sort((a, b) => b.value - a.value);

d3
  .treemap()
  .tile(d3.treemapResquarify)
  .size([iw, ih])
  .paddingOuter(6)
  .paddingTop((d) => (d.depth === 1 ? 30 : 0))
  .paddingInner(3)
  .round(true)(root);

const divisionNodes = root.children;
const projectNodes = root.leaves();

function relativeLuminance(hex) {
  const { r, g, b } = d3.rgb(hex);
  const chan = (v) => {
    const c = v / 255;
    return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
  };
  return 0.2126 * chan(r) + 0.7152 * chan(g) + 0.0722 * chan(b);
}
function labelColorFor(hex) {
  return relativeLuminance(hex) > 0.45 ? "#1A1A17" : "#FFFFFF";
}

// --- SVG mount ------------------------------------------------------------
const svg = d3.select("#container").append("svg").attr("width", width).attr("height", height);
const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);

// --- Division panels (tinted background + header label) -----------------
const divisionGroup = g.selectAll("g.division").data(divisionNodes).join("g").attr("class", "division");

divisionGroup
  .append("rect")
  .attr("x", (d) => d.x0)
  .attr("y", (d) => d.y0)
  .attr("width", (d) => d.x1 - d.x0)
  .attr("height", (d) => d.y1 - d.y0)
  .attr("fill", (d) => color(d.data.name))
  .attr("fill-opacity", 0.12)
  .attr("stroke", (d) => color(d.data.name))
  .attr("stroke-width", 1.5);

divisionGroup
  .append("text")
  .attr("x", (d) => d.x0 + 10)
  .attr("y", (d) => d.y0 + 20)
  .attr("fill", t.ink)
  .style("font-size", "16px")
  .style("font-weight", "600")
  .style("font-family", "system-ui, sans-serif")
  .text((d) => d.data.name);

// --- Project tiles (leaves), shaded by rank within their division -------
const projectGroup = g.selectAll("g.project").data(projectNodes).join("g").attr("class", "project");

projectGroup.each(function (d) {
  const siblings = d.parent.children;
  const rank = siblings.indexOf(d);
  const baseColor = color(d.parent.data.name);
  const shaded = d3.color(baseColor).darker(rank * 0.32);
  d.fill = shaded.formatHex();
  d.label = labelColorFor(d.fill);
});

projectGroup
  .append("rect")
  .attr("x", (d) => d.x0)
  .attr("y", (d) => d.y0)
  .attr("width", (d) => d.x1 - d.x0)
  .attr("height", (d) => d.y1 - d.y0)
  .attr("fill", (d) => d.fill)
  .attr("stroke", t.pageBg)
  .attr("stroke-width", 2);

const labelableProjects = projectGroup.filter((d) => d.x1 - d.x0 > 90 && d.y1 - d.y0 > 34);

labelableProjects
  .append("text")
  .attr("x", (d) => d.x0 + 8)
  .attr("y", (d) => d.y0 + 20)
  .attr("fill", (d) => d.label)
  .style("font-size", "13px")
  .style("font-weight", "600")
  .style("font-family", "system-ui, sans-serif")
  .text((d) => d.data.name);

labelableProjects
  .filter((d) => d.y1 - d.y0 > 52)
  .append("text")
  .attr("x", (d) => d.x0 + 8)
  .attr("y", (d) => d.y0 + 38)
  .attr("fill", (d) => d.label)
  .attr("opacity", 0.85)
  .style("font-size", "12px")
  .style("font-family", "system-ui, sans-serif")
  .text((d) => `$${d.data.value}k`);

// --- Title --------------------------------------------------------------
svg
  .append("text")
  .attr("x", width / 2)
  .attr("y", 50)
  .attr("text-anchor", "middle")
  .attr("fill", t.ink)
  .style("font-size", "22px")
  .style("font-weight", "600")
  .style("font-family", "system-ui, sans-serif")
  .text("treemap-basic · javascript · d3 · anyplot.ai");

svg
  .append("text")
  .attr("x", width / 2)
  .attr("y", 82)
  .attr("text-anchor", "middle")
  .attr("fill", t.inkSoft)
  .style("font-size", "15px")
  .style("font-family", "system-ui, sans-serif")
  .text("R&D Budget Allocation by Division and Project ($ thousands)");

Part of Basic Treemap on anyplot.ai.

Other implementations