DEV Community

Cover image for D3.js adoption guide: Overview, examples, and alternatives
Matt Angelosanto for LogRocket

Posted on • Originally published at blog.logrocket.com

D3.js adoption guide: Overview, examples, and alternatives

Written by Eze Sunday
✏️

D3.js is a JavaScript library that allows you to create tailored data visualizations. While most tutorial examples use charts to illustrate its usage, D3.js is a lot more powerful than a traditional charting library. It allows you to create highly custom, flexible data visualizations in many different formats.

In this guide, our goal is to give you all the information you need to convince your team to use D3.js or determine whether an alternative might better suit your needs. If you are considering D3.js for your project, let’s get into the details so you can make your final decision.


Background and history of D3.js

D3.js originated from Protovis, a declarative JavaScript graphical data visualization library that was created by Mike Bostock and Jeff Heer of the Stanford Visualization Group, with significant help from Vadim Ogievetsky.

Protovis was first released in April 2009 and was discontinued after its final v3.3.1 on June 28, 2011. D3.js was invented by the same team and built on many of the concepts of Protovis, making a big leap forward from Protovis with improved support for animation, interactions, and flexibility.


Why use D3.js?

There are several data visualization libraries in the JavaScript ecosystem. However, D3.js has been at the forefront for several years. Not only this, but D3.js is also the underlying library behind many other available data visualization libraries.

Some of the reasons why I typically prefer D3.js over other data visualization libraries include:

  • Flexibility: D3.js makes it possible to create high-level tailored visualizations for your specific needs. This type of flexibility is one you can’t really get from other libraries. It gives you the power to create whatever visualization you desire
  • Scalability: D3.js is designed to be scalable. In the past, browser limitations caused performance to become an issue for projects with massive data in the billions. But today, that is no longer an issue — we can leverage server-side rendering to transfer data-intensive visualizations to the server. This should make D3.js suitable for large datasets and complex visualization at scale
  • Customizability: Every aspect of the data visualizations you create with D3.js will likely involve writing the code yourself, giving you full control over how it looks and behaves. It’s the type of data visualization library you’ll want to use when you need to create a specific kind of visualization that describes your data in the best way possible, tailored to your own needs
  • Active community: D3.js has an active developer community with over 107k GitHub stars and regular updates to their GitHub repository. This is something I always look out for when choosing a library for my project, as a well-maintained project with an active community is likely to provide a high level of support
  • Framework agnostic: A lot of other data visualization libraries are tailored to a particular JavaScript library or framework. For example, Victory and Visx are visualization libraries designed to work with React only. However, D3.js can be implemented for any framework at all

While I admire D3.js, I think it’s also fair to mention that it’s not a perfect library. It also has some cons, including:

  • Steep learning curve: Since you get to build every part of the visualisation from the ground up, you need a reasonable grasp of the fundamentals of D3, SVG, HTML, and CSS. Otherwise, it might take much longer to get what you need done
  • Not ideal for basic chart visualization: If you only need to create simple charts for basic data exploration, D3.js might be overkill. Other libraries offer simpler solutions for these cases
  • Lack of prebuilt templates: Unlike a lot of other visualization libraries, D3.js does not have prebuilt templates, like charts that allow you to just feed them some data. Keep in mind that there is a long list of charting libraries and tools that leverage D3.js to enable you to build visualizations a lot faster without worrying about the low-level D3.js details

Further reading:


How D3.js works

Now that we’ve gone over the background, benefits, and drawbacks of D3.js, let’s explore how it works.

D3.js takes both the data to be visualized and the graphics you want to use for the visualization and binds them to the DOM in a flexible way, allowing you to manipulate, add, or update your data easily. This makes it possible for you to build very complex visualizations customized to your needs.

For example, the code below will render a simple bar chart in the browser. You can easily copy and paste it into your code editor to test it:

<!DOCTYPE html>
<div id="simple-chart"></div>
<script type="module">
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
// Set chart dimensions.
const width = 300;
const height = 150;
// Sample data.
const data = [10, 20, 30, 40, 50];
// Create SVG container.
const svg = d3.create("svg")
    .attr("width", width)
    .attr("height", height);
// Create bars for each data point.
svg.selectAll("rect")
    .data(data)
    .enter()
    .append("rect")
    .attr("x", (d, i) => i * 60)
    .attr("y", d => height - d)
    .attr("width", 50)
    .attr("height", d => d)
    .attr("fill", "steelblue");
let chartContainer = document.getElementById("simple-chart");
// Append SVG to the chart container.
chartContainer.append(svg.node());
</script>
Enter fullscreen mode Exit fullscreen mode

The code above will render the following bar chart: Demo Of A Simple Bar Chart Created Using D3 Js Let’s break down a few notable parts of the code block above. One thing you’ll notice is that every part of the bar chart is drawn on top of an svg container:

const svg = d3.create("svg")
    .attr("width", width)
    .attr("height", height);
Enter fullscreen mode Exit fullscreen mode

This is because SVG makes it a lot easier to draw shapes. For example, a rect is a built-in SVG element that defines a rectangle shape.

We selected all existing rect elements — and made sure to create a new rect for each data element if it didn’t already exist — with the help of the enter() function:

svg.selectAll("rect")
    .data(data)
    .enter()
    .append("rect")
    .attr("x", (d, i) => i * 60)
    .attr("y", d => height - d)
    .attr("width", 50)
    .attr("height", d => d)
    .attr("fill", "steelblue");
Enter fullscreen mode Exit fullscreen mode

Finally, we append the SVG we created to the D3 object, as shown in this part of the code:

<div id="simple-chart"></div>
let chartContainer = document.getElementById("simple-chart");
// Append SVG to the chart container.
chartContainer.append(svg.node());
Enter fullscreen mode Exit fullscreen mode

This is just the tip of the iceberg for what you can do with D3.js. To get a better sense of this library’s capabilities, let’s look at some of its standout features.

Further reading:


Key D3.js features to know

Digging deep into the D3.js documentation is the recommended way to gain in-depth knowledge of the tool. However, if you’re looking to evaluate the functionalities and start practicing immediately, here are some key features to look out for.

Visualization tools

D3.js gives you the tools to create any kind of data visualization you can imagine by leveraging your skills in D3.js, JavaScript, HTML, and CSS.

You can create graphs, charts, scatter plots, and several other types of visuals. It’s also possible to combine D3.js with other graphics libraries like Three.js to build even more amazing graphics. For example, here is an example of a 3D globe created with D3.js and Three.js: Demo Showing A 3D Globe Created Using D3 Js

Further reading:

Selecting elements

D3.js allows you to select HTML elements with the select and selectAll methods as shown in our initial example. These methods can be used like so:

svg.selectAll("rect")

//or

svg.select("rect")
Enter fullscreen mode Exit fullscreen mode

In the above snippet, d3.select allows you to select the first matching rect element. Meanwhile, d3.selectAll selects all matching rect elements.

DOM manipulation

D3.js allows you to leverage JavaScript and CSS to manipulate the DOM to achieve your desired visualization result. You can directly create, update, and delete elements based on data or your project requirements.

For example, you could use append to add new elements, remove to delete, and attr to set attributes, like so:

// Select the body element
var bodySelection = d3.select("body");

// Append a paragraph
bodySelection.append("p")
  .text("This is a new paragraph.");

// Wait for 2 seconds and then remove the paragraph
setTimeout(function() {
  bodySelection.select("p").remove();
}, 2000);

// Append a div with a class and style
bodySelection.append("div")
  .attr("class", "my-div")
  .style("width", "100px")
  .style("height", "100px")
  .style("background-color", "lightblue")
  .text("I'm a div with attributes!");

// Wait for 2 seconds and then change the text content
setTimeout(function() {
  bodySelection.select(".my-div").text("Text updated!");
}, 4000);
Enter fullscreen mode Exit fullscreen mode

Data joining

Data joining in D3.js is about connecting your data to the visual elements you're creating.

In a previous example, we used selectAll() to select all the rect elements — even though they did not yet exist — and then loaded data to the rect. We then used enter and append to join the data to each rectangle. That’s exactly what data joining is.

In the below example, we’re joining data to selected rectangles directly:

svg.selectAll("rect")
    .data(data)
    .enter()
    .append("rect")
Enter fullscreen mode Exit fullscreen mode

There are a lot of other methods like this that you can find in the D3.js documentation.


Use cases for D3.js

There are several use cases for D3.js, but let’s highlight three key use cases:

  • Real-time data visualization: Picture a scenario where you want to display real-time updates with dynamic charts and graphs that adjust as new data arrives. That’s a perfect candidate for D3.js, as this library plays nicely with dynamic data and interactivity
  • Interactive charts and graphs: If you are looking to create tailored, dynamic, and interactive charts for data presentation on websites, D3.js is a great JavaScript library for that sort of thing
  • Geospatial data visualization: D3.js allows you to show geographical data visually, like interactive maps or choropleth maps. The image below is an example of an interactive map that can be built with D3.js:

Demo Of An Interactive Map Created Using D3 Js

These are some of the most common use cases for D3.js, but since the library allows you to create completely custom data visualizations, the only limit is your imagination!


Styling and animating D3.js

D3.js allows you to use native CSS to style your data visualizations. It provides a styling method that allows you to pass conventional CSS styles to your visualizations as shown below:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    <div id="map"></div>
    <script type="module" src="https://cdn.jsdelivr.net/npm/d3@7"></script>
    <script type="module">
        const svg = d3.select("#map").append("svg").attr("width", 100).attr("height", 100);
        svg.selectAll("circle")
            .data([1, 2, 3])
            .enter().append("circle")
            .attr("cx", d => d * 20)
            .attr("cy", 50)
            .attr("r", 10)
            .style("fill", "blue")
            .style("stroke", "white")
            .style("stroke-width", 2);
    </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

In the code above, we used the providing styling method to change the color of the SVG stroke to white, paint each circle’s background with a blue hue, and add a stroke-width of 2.

You can also choose to write your styles in the style tag or in a different CSS file. For example, here is the same code, but with the CSS file separated in the style tag:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    .svg-elements {
      fill: blue;
      stroke: white;
      stroke-width: 2;
    }
    #map {
      border: 1px solid #ccc;
      width: 100px; /* Adjust the width as needed */
      height: 100px; /* Adjust the height as needed */
    }
  </style>
</head>
<body>
  <div id="map"></div>
  <script type="module">
    import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
    // Create an SVG element
    const svg = d3.select("#map").append("svg");
    // Add circles to the SVG
    svg.selectAll("circle")
      .data([1, 2, 3]) // example data, replace with your own
      .enter().append("circle")
      .attr("cx", d => d * 20)
      .attr("cy", 50)
      .attr("r", 10);
    // Apply the class to style the circles
    svg.selectAll("circle").classed("svg-elements", true);
  </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

The output will look like so: Final Web App


Deploying your D3.js project

D3 project deployment is straightforward. Just run your normal library or framework bundler and it will be bundled together!

You don’t need to do anything special to make D3.js work, since D3.js code is just JavaScript, HTML, and CSS. So, you’ll deploy it together with your existing project without any additional requirements.


Other factors to weigh when considering D3.js

We’ve learned a lot about D3.js already, but there are a few additional considerations you should keep in mind while deciding whether or not to adopt this library into your project.

  • Performance: Even though D3.js was optimized to handle large datasets, the browser might not be able to handle extreme amounts of data. As we mentioned earlier, you might want to offload some of the data processing to the backend and render your visualization in batches with aggregations
  • DX/Ease of use: D3.js is straightforward for very simple visualizations, but for more complex needs, you’ll need a better understanding of the D3.js library. If all you need is a simple charting library, you may be better off using libraries that provide templates where you can simply supply the required data to generate your charts. On the other hand, D3.js is an excellent tool for creating highly custom data visualizations, in which case the trouble of learning the fundamentals and practicing using this library tends to pay off in the long run
  • Bundle size: The D3.js library file size is about 873kB as of the time of this writing. It’s also tree-shakable, which means it will include only the code required by your application to work effectively in your production bundle, so you won’t end up with an over-bloated build
  • Documentation: One of the best things about D3.js documentation is that it has lots of examples. For almost every concept, there is a theoretical explanation along with an example to show you exactly how it works, from basic examples to more complex ones
  • Supported data sources: D3.js supports many data sources, including JSON, CSV, GeoJSON, HTML table data, and JavaScript arrays and objects. This allows you to load your data in almost any format you want to

There are special methods that allow you to load your data into D3.js for different data sources. Let’s see some of the methods for popular data sources like CSV, JSON, arrays and objects, tabular HTML data, and GeoJSON.

CSV:

d3.csv("your_data.csv").then(function(data) {
    // Process csv data here
});
svg.selectAll("rect")
    .data(data)
    .enter()
...
Enter fullscreen mode Exit fullscreen mode

JSON:

d3.json("your_data.json").then(function(data) {
    svg.selectAll("rect")
        .data(data)
        ...
});
Enter fullscreen mode Exit fullscreen mode

Arrays/objects:

var data = [1, 2, 3, 4, 5];
// Or
var data = { key1: value1, key2: value2, ... };
svg.selectAll("rect")
    .data(data)
    ...
Enter fullscreen mode Exit fullscreen mode

Tabular data in HTML:

var data = d3.selectAll("table tr").data();
Enter fullscreen mode Exit fullscreen mode

GeoJSON:

d3.json("your_geojson_data.json").then(function(geoData) {
    svg.selectAll("rect")
    .data(geoData)
});
Enter fullscreen mode Exit fullscreen mode

D3.js vs. similar libraries

There are lots of libraries that allow you to create data visualizations, but none currently beats the flexibility and depth of D3.js. We’ve compared the top charting libraries— including D3 — in previous posts on the LogRocket blog, which you can peruse under “Further reading” below.

It’s important to acknowledge that D3.js has taken a huge market share in the data visualization space. A lot of other similar options actually use D3.js behind the scenes. Those that don’t use D3.js under the hood also don’t give you the type of flexibility that D3.js provides.

Further reading:


Conclusion

D3.js is an amazing JavaScript data visualization library designed for highly performant, tailored visualizations. It’s the type of visualization library you want to use when you want to visualize your data in very custom ways or to meet particular project requirements.

While D3.js is a great choice for many use cases, sometimes, you might just want to create simple charts and graphs. In such cases, you might want to use simpler data visualization options or tools that allow you to leverage D3.js without worrying about the low-level details.

Make sure you weigh all your project requirements to determine whether D3.js is appropriate for your needs. Feel free to comment below with questions or to share your D3.js projects. Happy visualizing!


Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.

NPM:

$ npm i --save logrocket 

// Code:

import LogRocket from 'logrocket'; 
LogRocket.init('app/id');
Enter fullscreen mode Exit fullscreen mode

Script Tag:

Add to your HTML:

<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
Enter fullscreen mode Exit fullscreen mode

3.(Optional) Install plugins for deeper integrations with your stack:

  • Redux middleware
  • ngrx middleware
  • Vuex plugin

Get started now

Top comments (1)

Collapse
 
citronbrick profile image
CitronBrick

I've used D3.
I feel it lacks an attr({cx: 5, cy:10, color: 'red'}) kind of method (like in jQuery) to set multiple attributes at one go.