HAHS.
Back to Catalog

Circle Packing

chart

Also known as: packed circles, bubble hierarchy, circular treemap

Show hierarchyShow composition HierarchicalNumericalCategorical Enclosure

Description

Circle packing is an enclosure-based hierarchical visualization where each node in a tree is represented by a circle. Leaf nodes are sized proportionally to their quantitative value, and parent nodes are drawn as larger circles that contain their children. The outermost circle represents the root of the hierarchy, and successive levels of nesting reveal the tree structure through spatial containment.

Unlike treemaps, which fill all available space with rectangles, circle packing inherently wastes space in the gaps between packed circles. This is actually a feature for readability: the white space between circles makes it easier to perceive individual elements and the nesting structure. The trade-off is that circle packing is less space-efficient than treemaps, so it is better suited for moderate-sized hierarchies where clarity is valued over density.

Circle packing produces an aesthetically pleasing, organic layout that many audiences find more approachable than the sharp rectangles of a treemap. The algorithm works by iteratively placing circles adjacent to each other while minimizing the enclosing circle’s radius. Color is typically used to encode category (the branch of the hierarchy a node belongs to), while size encodes the quantitative value.

Circle Packing — hierarchical data shown as sized circles grouped by parent

When to Use

  • Visualizing hierarchical data where both the tree structure and leaf values matter
  • When the organic, approachable aesthetic of circles is preferred over the density of a treemap
  • Showing part-to-whole relationships within a multi-level hierarchy
  • Interactive exploration with drill-down: clicking a parent zooms into its children

When NOT to Use

  • When space efficiency is critical — treemaps fill 100% of the space; circle packing wastes ~9% in gaps
  • When precise size comparison matters — circles are harder to compare than aligned rectangles
  • For very deep hierarchies (>4 levels) — nesting becomes difficult to read
  • For flat (non-hierarchical) data — use a bubble chart instead

Anatomy

  • Root circle: The outermost circle encompassing the entire hierarchy.
  • Branch circles: Intermediate circles representing parent nodes, containing their children.
  • Leaf circles: The innermost circles sized by quantitative value.
  • Nesting: Spatial containment encodes parent-child relationships.
  • Color encoding: Fill color indicates category or branch membership.
  • Labels: Text placed inside circles for leaf nodes large enough to accommodate text.
  • White space: Gaps between circles that aid visual separation and perception of hierarchy levels.

Variations

  • Flat circle packing: No nesting — all circles are at the same level, packed into a container. Effectively a bubble chart with optimal packing.
  • Zoomable circle packing: Clicking a parent circle smoothly zooms into it, revealing children at a larger scale. Popularized by Mike Bostock’s D3 examples.
  • Color-encoded depth: Instead of category, color encodes hierarchy depth, creating a gradient from outer to inner levels.
  • Force-packed circles: Uses force simulation instead of mathematical packing, allowing animated transitions as data changes.

Code Reference

// D3 Circle Packing
import * as d3 from "d3";

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

d3.pack()
  .size([width, height])
  .padding(3)(root);

const svg = d3.select("#chart").append("svg")
  .attr("viewBox", [0, 0, width, height]);

svg.selectAll("circle")
  .data(root.descendants())
  .join("circle")
  .attr("cx", d => d.x)
  .attr("cy", d => d.y)
  .attr("r", d => d.r)
  .attr("fill", d => d.children ? "none" : color(d.data.category))
  .attr("stroke", d => d.children ? "#999" : "none")
  .attr("fill-opacity", 0.7);