Let's Make a Bar Chart
This brief introduction to D3 provides an example of how to use D3 to create a simple bar chart. It will show to map an array of data to a set of bars (represented as DIVs on a web page) where the lengths of the bars represent the values found in the data.
The example on this page is based on the official D3.js tutorial of the same name which can be found on Observable. Observable notebooks are a fun and powerful tool for experimenting with data using JavaScript. However, they also introduce their own syntax and quirks. In this tutorial, we try to strip away all of those "special" coding practices and show how to achieve the result in plain JavaScript.
Note that this is just the first of a set of examples in the Let's Make a Bar Chart series. Be sure to view them all using the menus at the top!
Starting with Data
In this example, we will create a bar chart to represent an array of numbers. We'll start with a simple array of numbers. Our goal will be to create a bar chart to display these numbers in a web page.
let data = [4, 8, 15, 16, 23, 42];
Data in a Web Page
Suppose the data above was defined within a simple web page using the script tag as shown below. You'll notice that
the D3 library is also included since we'll be using that to create the bar chart. By including the D3 library,
a global variable named d3
is defined. That global variable gives
us access to all of d3's functionality.
<html>
<body>
<script src="https://d3js.org/d3.v7.min.js"></script>
<div class="chart">
</div>
<script>
// This is the data array which will be represented as a bar chart.
let data = [4, 8, 15, 16, 23, 42];
</script>
</body>
</html>
If you look closely at the code above, you will also see that there is a div
at the bottom of the
page with class "chart". This is the place on the page where we'll add the bar chart. We'll accomplish this by
adding new elements to the web page as children of this "chart" div
. For each bar in the bar chart,
we'll append to the page a new div
whose width is proportional to the corresponding number in the
data
array.
Creating a D3 Selection
Before we can append a set of new div
elements (one for each value in the data array) to the "chart"
div
, we need to
D3 makes it easy to select an item from a web page using an element type, a class name, or an element ID. D3
uses the same notation that CSS uses for classes (a . prefix) and IDs (a # prefix). So, if we want to select
the "chart" div, we can reference it as ".chart" as follows: d3.select(".chart")
. The code
below shows this selection statement within the larger web page.
<html>
<body>
<script src="https://d3js.org/d3.v7.min.js"></script>
<div class="chart">
</div>
<script>
// This is the data array which will be represented as a bar chart.
let data = [4, 8, 15, 16, 23, 42];
// Select the chart div which will be the container for the new bar chart
let chart = d3.select(".chart");
</script>
</body>
</html>
Using the D3 Data Join to Add the Bars
We're now ready to create the main elements o the bar chart using D3's div
based on the value of a number in a data array).
We begin with the chart
variable which is a D3 selection containing the element which will be the
container for our bar chart. We then use D3's .selectAll(...)
to select all div
elements
that within chart
. This call to chart.selectAll("div")
will return an empty selection
because the chart
div is initially empty in our web page.
We next add a call to D3's .data(...)
on that empty selection to link it with the data array we aim
to visualize in the bar chart. In the code listing below, you'll see chart.selectAll("div").data(data)
for this step. Next, we call .join("div")
which tells D3 that we want to append new div
elements for each new data item. You can read more about the
join function in D3's documentation
or via a short tutorial on Observable.
The remaining code for this section sets a number of style attributes for each div that is added to the web page. It sets some constant values that are the same for all bars (e.g., background color and font), as well as some attributes that are data-driven. Notice that the width and text values are "functions of d" in the code below. This is what gives D3 (data-driven documents) it's name! New document elements (in this case, divs) are added to represent the items in the data array, and the properties of those elements are determined by the values of those items in the data array.
Here is the entire example so far, and below the code you'll see the output that this code creates.
<html>
<body>
<script src="https://d3js.org/d3.v7.min.js"</script>
<div class="chart">
</div>
<script>
// This is the data array which will be represented as a bar chart.
let data = [4, 8, 15, 16, 23, 42];
// Select the chart div which will be the container for the new bar chart
let chart = d3.select(".chart");
// Perform the data join and create divs for each item in our data array. Notice that both the width
// and the text for each div are derived as a function of the data. The other style attributes are
// data independent.
chart.selectAll("div")
.data(data).join("div")
.style("background", "steelblue")
.style("color", "white")
.style("text-align", "right")
.style("font", "10px san-serif")
.style("padding", "3px")
.style("margin", "1px")
.style("width", d => d+"px")
.text(d => d);
</script>
</body>
</html>
Here is the output produced by this code. You'll see we have 6 divs, one for each item in our data array. The divs have numbers corresponding to the values in the data array, and the width of each bar measured in pixels is equal to the values in the data array. Our first bar chart! But it's really narrow... so we still have some work to do.
Creating a Scale
In the previous section, we created a set of div
elements and set the width of each to the same
value as the numbers in the data array. This worked, but notice how narrow the chart is! Since our data's max
value is just 42, our chart is just 42 pixels across. That's pretty small on a normal monitor. It sure would
be nice to create a bigger chart... say 500 pixels across.
D3 provides a different types of
We can define a D3 scale to accomplish this using linear interpolation as shown below. We store our scale in a
variable named x
because it represents the scale for the horizontal x axis of our bar chart.
let x = d3.scaleLinear()
.domain([0, d3.max(data)])
.range([0, 500]);
All we need to do is insert this scale into our overall web page and use it when setting the width of the
div
s.
<html>
<body>
<script src="https://d3js.org/d3.v7.min.js"></script>
<div class="chart">
</div>
<script>
// This is the data array which will be represented as a bar chart.
let data = [4, 8, 15, 16, 23, 42];
// Define an x scale.
let x = d3.scaleLinear()
.domain([0, d3.max(data)])
.range([0, 500]);
// Select the chart div which will be the container for the new bar chart
let chart = d3.select(".chart");
chart.selectAll("div")
.data(data).join("div")
.style("background", "steelblue")
.style("color", "white")
.style("text-align", "right")
.style("font", "10px san-serif")
.style("padding", "3px")
.style("margin", "1px")
.style("width", d => x(d)+"px")
.text(d => d);
</script>
</body>
</html>
That's it! Here is what our final chart looks like once we've used a scale to give 500 pixels in width.
Next Steps...
Want to experiment with an interactive version of this program? Click here!
Ready to learn more? Click here to try creating a version of this chart with SVG!