Data-Driven Documents
D3 (Data-Driven Documents) is a low-level JavaScript library for creating custom data visualizations by binding data to DOM elements and applying data-driven transformations. Unlike high-level charting libraries that provide pre-configured chart types, D3 gives you complete control over the visual output by providing primitives for data manipulation, DOM selection, geometric calculations, and transitions. With over 7 million weekly downloads, it's the de facto standard for complex, interactive visualizations on the web.
The library's architecture is built around the data join pattern—a declarative approach to synchronizing data with DOM elements through enter, update, and exit selections. When your data changes, D3 efficiently updates only the affected elements rather than re-rendering everything. This approach, combined with D3's synchronous execution model, makes debugging straightforward since operations happen immediately when called rather than being queued in an event loop.
D3 operates at a lower abstraction level than frameworks like Chart.js or Recharts, requiring more code to create visualizations but offering unmatched flexibility. It provides modules for scales, axes, shapes, layouts (force-directed graphs, treemaps, chord diagrams), geographic projections, and animation. The library integrates well with modern frameworks like React, Vue, and Svelte—you can use D3 for calculations and geometry while letting the framework handle rendering, or use D3 to directly manipulate the DOM for performance-critical visualizations.
D3 has maintained a stable API for over a decade with comprehensive documentation. Version 7 modernized the codebase with ES modules, allowing you to import only the specific modules you need. The library has minimal dependencies and works directly with web standards (SVG, Canvas, HTML), making it a future-proof choice for projects requiring custom visualization capabilities beyond what pre-built charting libraries offer.
import { select, scaleLinear, scaleBand, axisBottom, axisLeft, max } from 'd3';
const data = [
{ category: 'Q1', value: 45 },
{ category: 'Q2', value: 72 },
{ category: 'Q3', value: 58 },
{ category: 'Q4', value: 91 }
];
const width = 600;
const height = 400;
const margin = { top: 20, right: 20, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const svg = select('#chart')
.append('svg')
.attr('width', width)
.attr('height', height);
const g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
const xScale = scaleBand()
.domain(data.map(d => d.category))
.range([0, innerWidth])
.padding(0.2);
const yScale = scaleLinear()
.domain([0, max(data, d => d.value)])
.range([innerHeight, 0])
.nice();
g.append('g')
.attr('transform', `translate(0,${innerHeight})`)
.call(axisBottom(xScale));
g.append('g')
.call(axisLeft(yScale));
g.selectAll('.bar')
.data(data)
.join('rect')
.attr('class', 'bar')
.attr('x', d => xScale(d.category))
.attr('y', d => yScale(d.value))
.attr('width', xScale.bandwidth())
.attr('height', d => innerHeight - yScale(d.value))
.attr('fill', 'steelblue')
.on('mouseenter', function(event, d) {
select(this).attr('fill', 'orange');
console.log(`${d.category}: ${d.value}`);
})
.on('mouseleave', function() {
select(this).attr('fill', 'steelblue');
});Custom dashboard visualizations: Building analytics dashboards that require non-standard chart types or highly customized interactions like linked brushing across multiple charts, custom tooltips with rich HTML content, or real-time data updates with smooth transitions.
Geographic data visualization: Creating choropleth maps, cartograms, or geographic network visualizations using D3's projection system and GeoJSON support. Examples include election result maps, disease outbreak tracking, or logistics network visualization.
Network and hierarchical data: Visualizing organizational charts, dependency graphs, social networks, or file system structures using force-directed layouts, tree diagrams, circle packing, or sunburst charts that require custom node rendering and interaction behaviors.
Scientific and statistical visualization: Rendering complex scientific data like probability distributions, heatmaps, contour plots, or multi-dimensional data projections where precise control over mathematical transformations and visual encoding is essential.
Interactive storytelling and journalism: Creating scrollytelling experiences where visualizations animate and transform as users scroll, or building interactive articles with data-driven narratives that require tight coordination between DOM manipulation and data updates.
npm install d3pnpm add d3bun add d3