You will be able to create a simple SVG bar chart in JavaScript by binding an array of numbers to rect elements with D3.js.
What it is
D3.js, short for Data-Driven Documents, is a JavaScript library for building custom visualisations by binding data to DOM elements, especially SVG shapes. The core mental model is a data join: you select elements, attach data to them, then create, update, or remove elements based on that data. Related terms include selection, datum, enter, update, exit, scales, and axes.
Why it matters
- It lets you build visualisations that are not available in standard chart libraries.
- It keeps the visual elements tied to data, so updates can be incremental.
- It works directly with SVG, HTML, and Canvas, giving precise control over rendering.
- It supports data transformations such as sorting, grouping, and scaling.
- It is useful for interactive dashboards, maps, timelines, and custom charts.
Syntax or steps
The smallest useful pattern is:
d3.select("svg")
.selectAll("rect")
.data(data)
.join("rect")
.attr("x", (d, i) => i * 50)
.attr("y", d => 100 - d)
.attr("width", 40)
.attr("height", d => d);
d3.select chooses a container. selectAll creates a selection of elements to bind. data attaches the array. join creates missing elements, updates existing ones, and removes extra ones. attr sets SVG attributes using the bound data.
Example
<div id="chart"></div>
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
<script>
const data = [12, 30, 22, 45, 18];
const svg = d3.select("#chart")
.append("svg")
.attr("width", 300)
.attr("height", 150);
svg.selectAll("rect")
.data(data)
.join("rect")
.attr("x", (d, i) => i * 55)
.attr("y", d => 150 - d * 3)
.attr("width", 45)
.attr("height", d => d * 3)
.attr("fill", "steelblue");
</script>
Part by part:
const datais the array of values to visualise.d3.select("#chart")selects the container element..append("svg")creates an SVG canvas inside it.svg.selectAll("rect")starts with an empty selection of rectangles..data(data)binds each number to a future rectangle..join("rect")creates one rectangle per data value..attr(...)positions and sizes each rectangle usingdandi.
Common mistakes
- Using
.append()without.join()or.enter(). This can duplicate elements when the code runs again. Use.join("rect")for simple cases. - Forgetting removed data. If the array shrinks, old elements may remain.
.join()handles removal automatically. - Hard-coding pixel values. For real charts, use a scale such as
d3.scaleLinear()to map data values to pixel positions. - Selecting the wrong elements.
selectAll("rect")must match the elements you intend to bind; otherwise D3 may update unrelated shapes.
When to use it
| Use D3.js when | Use a higher-level chart library when |
|---|---|
| You need custom shapes, interactions, or layouts. | You need a standard bar, line, or pie chart quickly. |
| You want full control over SVG and data binding. | You prefer simple configuration options. |
| The visualisation is part of a larger interactive application. | The chart can be rendered from a fixed dataset with little customisation. |
Practice
Guided exercise: Add a text label above each bar showing its value.
svg.selectAll("text")
.data(data)
.join("text")
.attr("x", (d, i) => i * 55 + 22)
.attr("y", d => 150 - d * 3 - 5)
.attr("text-anchor", "middle")
.text(d => d);
Challenge: Sort the data from largest to smallest, then run the chart code again. Hint: use data.sort((a, b) => b - a) before the selection code.
Quick check
Question: What does .data(data) do in a D3 selection?
Answer: It binds each item in the array to the selected elements and returns a data join, allowing D3 to create, update, or remove elements based on the data.
Summary
D3.js turns data into visual elements by joining arrays to DOM or SVG nodes. The key idea is that each element can carry a datum, and functions can use that datum to set position, size, colour, or text. This makes D3 powerful for custom, data-driven visualisations.