Skip to content
D3.js Basics Explained — Complete Guide to Setup, Selections & Data Join

D3.js Basics Explained — Complete Guide to Setup, Selections & Data Join

DodaTech Updated Jun 6, 2026 13 min read

D3.js is a JavaScript library for producing dynamic, interactive data visualizations in web browsers using HTML, SVG, and CSS to bring data to life.

What You’ll Learn

By the end of this tutorial, you will be able to:

  • Understand what D3.js is and why it’s different from charting libraries
  • Install D3.js via CDN, npm, or download
  • Select and manipulate DOM elements using D3 selections
  • Chain D3 methods fluently
  • Bind data to DOM elements using the data join pattern
  • Work with the enter, update, and exit lifecycle
  • Build a simple bar chart from scratch

Why D3.js Basics Matters

Imagine you’re building a real-time CPU usage monitor for Durga Antivirus Pro — you need full control over every pixel, every animation, and every data binding. High-level charting libraries like Chart.js feel restrictive when you need custom interactions. D3.js gives you that control. It’s the same technology used in Doda Browser’s performance dashboard to render memory usage graphs. Understanding D3.js basics is your first step toward building professional, custom data visualizations that can power security tools, analytics dashboards, and interactive reports.

Learning Path

    flowchart LR
    A["D3.js Basics"] --> B["D3.js SVG"]
    B --> C["D3.js Scales & Axes"]
    C --> D["D3.js Charts"]
    D --> E["D3.js Interactions"]
    D --> F["D3.js Data Handling"]
    E --> G["D3.js Advanced"]
    F --> G
    G --> H["D3.js Reference"]
    A:::current
    
    classDef current fill:#4CAF50,color:#fff,stroke:#333,stroke-width:2px
  
Prerequisites: Basic knowledge of HTML, CSS, and JavaScript (variables, functions, arrays). You don’t need any prior experience with D3.js or data visualization.

What is D3.js?

Think of D3.js as a bridge between data and graphics. You have data (numbers, objects, CSV rows) and you want to turn it into visual elements on a screen. D3.js is the tool that connects the two.

D3.js is not a charting library — it’s a data-binding library. This is the single most important thing to understand. Chart.js gives you a pre-built bar chart where you just pass data. D3.js gives you building blocks — circles, rectangles, lines — and you assemble them into a chart yourself. More work, but total control.

D3.js Pipeline

┌──────────────────────────────────────────────────────┐
│                   D3.js Pipeline                       │
│                                                        │
│  Data → Selection → Data Join → Enter/Update/Exit →   │
│  SVG Attributes → Scales → Axes → Chart               │
└──────────────────────────────────────────────────────┘

Every D3.js visualization follows this pipeline. You start with data, select elements in the DOM, join the data to those elements, and then style them.

Key Concepts at a Glance

ConceptWhat It MeansAnalogy
SelectionPicking DOM elements to work withLike using a highlighter on a document
Data JoinLinking data to elementsLike assigning seats on a bus — each person (data) gets a seat (element)
EnterCreating elements for new dataAdding new chairs when more people arrive
ExitRemoving elements for removed dataRemoving chairs when people leave
ChainingCalling multiple methods in sequenceLike an assembly line — each step transforms the result

Installation

You need to load D3.js into your project before you can use it. There are three ways to do this.

Method 1: CDN (Simplest for Beginners)

Add this <script> tag to your HTML file. The CDN delivers the library from a fast server.

<!-- Latest stable version -->
<script src="https://d3js.org/d3.v7.min.js"></script>

Why use CDN? No download, no npm, no build tools. Just add the tag and start coding. Perfect for learning and simple projects.

Method 2: npm (For Professional Projects)

If you use a build tool like Vite, Webpack, or Parcel:

npm install d3
import * as d3 from "d3";

Why use npm? Version control, tree-shaking (removing unused code), and integration with modern JavaScript frameworks like React or Vue.

Method 3: Download

Download from d3js.org and host locally:

<script src="js/d3.v7.min.js"></script>

Which Version Should You Use?

VersionStatusUse For
D3 v7Latest stableNew projects
D3 v5Still widely usedLegacy projects
D3 v3/v4DeprecatedAvoid

Our recommendation: Use D3 v7 for all new projects. All examples in this tutorial use D3 v7.

Hello, D3.js!

Let’s write the simplest D3.js program — appending text to the page.

<!DOCTYPE html>
<html>
<head>
    <title>D3.js Hello World</title>
</head>
<body>
    <div id="container"></div>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <script>
        // Step 1: Select the container div
        // Step 2: Append a paragraph element inside it
        // Step 3: Set the text content
        d3.select("#container")
            .append("p")
            .text("Hello, D3.js!");
    </script>
</body>
</html>

What’s happening here? Line by line:

  1. d3.select("#container") — Finds the <div id="container"> element, like using document.querySelector.
  2. .append("p") — Creates a new <p> element inside the container.
  3. .text("Hello, D3.js!") — Sets the text content of that paragraph.

Output: A paragraph reading “Hello, D3.js!” appears inside the container div.

Always place your D3.js <script> tag after the HTML elements you want to select. If you put it in the <head>, the DOM elements won’t exist yet when the script runs. Alternatively, use document.addEventListener("DOMContentLoaded", ...).

Selections

Selections are D3’s way of finding elements in the DOM. If you’ve used jQuery, this will feel familiar — but D3 selections return special objects with chainable methods.

Selecting Elements

// Select the FIRST matching element
d3.select("p")           // First <p> on the page
d3.select("#myid")       // Element with id="myid"
d3.select(".myclass")    // First element with class="myclass"

// Select ALL matching elements
d3.selectAll("p")        // Every <p> on the page
d3.selectAll(".item")    // Every element with class="item"

Why two methods? d3.select() returns one element — useful when you want to work with a single chart container. d3.selectAll() returns all matches — useful when you want to bind an array of data to multiple elements.

Chaining Methods

The real power of selections is chaining — calling one method after another because each returns the selection.

d3.select("body")           // Select the <body>
    .append("div")           // Add a <div> inside it
    .attr("class", "box")    // Give it class="box"
    .style("color", "red")   // Make text red
    .text("Hello");          // Set its text

Think of chaining like an assembly line. Each station (method) does one job and passes the item to the next station.

Common Selection Methods

Here are the methods you’ll use most:

MethodWhat It DoesExample
.attr(name, value)Sets an HTML attribute.attr("width", 100)
.style(prop, value)Sets a CSS property.style("color", "red")
.text(string)Sets text content.text("Sales: $1,200")
.html(string)Sets inner HTML.html("<b>Bold</b>")
.append(tag)Adds a child element.append("circle")
.classed(name, bool)Toggles a CSS class.classed("active", true)
.remove()Removes from DOM.remove()

The Data Join — D3’s Superpower

The data join is what makes D3.js special. It’s the mechanism that binds an array of data to a selection of DOM elements.

The Problem Data Join Solves

Imagine you have a list of 5 numbers: [10, 20, 30, 40, 50]. You want to create 5 <li> elements, one for each number. Without D3, you’d write a loop:

let data = [10, 20, 30, 40, 50];
let list = document.getElementById("mylist");
for (let i = 0; i < data.length; i++) {
    let li = document.createElement("li");
    li.textContent = data[i];
    list.appendChild(li);
}

That works once. But what happens when data changes? What if you add a 6th number? Or remove the 3rd? Now you need to track which elements exist and which don’t. That’s tedious.

D3’s data join automates this.

How the Data Join Works

var data = [10, 20, 30, 40, 50];

// Step 1: Select ALL list items (even if none exist)
// Step 2: Bind data to the selection
var selection = d3.select("#list").selectAll("li").data(data);

When you call .data(data), D3 compares the data array against the selected elements and creates three virtual selections:

         Data: [10, 20, 30, 40, 50]
           │
           ▼
    ┌──────────────┐
    │   Data Join   │
    └───┬───┬───┬───┘
        │   │   │
        ▼   ▼   ▼
     Enter Update Exit
    (create) (modify) (remove)

Enter-Update-Exit Pattern

var data = [10, 20, 30, 40, 50];
var selection = d3.select("#list").selectAll("li").data(data);

// ENTER: Create <li> elements for new data items
selection.enter()
    .append("li")
    .text(function(d) { return d; });

// UPDATE: Modify existing elements
selection.text(function(d) { return d + " (updated)"; });

// EXIT: Remove elements that no longer have data
selection.exit().remove();

Let’s understand each phase:

Enter — For each data item that doesn’t have a corresponding DOM element, create one. If you start with no <li> elements and 5 data items, all 5 go through “enter”.

Update — For each data item that already has a DOM element, modify that element. If you re-render with the same 5 items, all 5 go through “update”.

Exit — For each DOM element that no longer has a data item, remove it. If you had 5 <li> elements but new data only has 3, 2 elements go through “exit”.

Why the Key Function Matters

By default, D3 matches data to elements by index — the first data item matches the first element, the second matches the second, and so on. This works fine when data doesn’t change order.

But what if your data has unique IDs and the order changes?

var data = [
    { id: 1, value: 50 },
    { id: 2, value: 80 },
    { id: 3, value: 120 }
];

// Use a key function to track elements by identity, not index
svg.selectAll("rect")
    .data(data, function(d) { return d.id; });

Why this matters: Without a key function, if data is sorted differently, elements get reshuffled in the DOM (causing visual flicker). With a key function, D3 tracks each item by its ID and updates it in place.

Method Chaining in Detail

Almost every D3 method returns the selection, allowing fluent chaining:

d3.select("body")
    .append("svg")
    .attr("width", 500)
    .attr("height", 300)
    .append("g")
    .attr("transform", "translate(50, 50)")
    .append("circle")
    .attr("r", 20)
    .attr("fill", "red");

What’s happening:

  1. Select <body>
  2. Append an <svg> element — the selection is now the SVG
  3. Set its width and height
  4. Append a <g> (group) inside the SVG — selection is now the group
  5. Translate the group 50px right, 50px down
  6. Append a circle inside the group
  7. Set its radius to 20 and fill to red

Common Mistakes

1. Forgetting to Call .enter() After .data()

// WRONG — nothing appears on screen
svg.selectAll("rect").data(data);

// RIGHT — creates elements for new data
svg.selectAll("rect").data(data).enter().append("rect");

Without .enter().append(), the data is bound to an empty selection (no <rect> elements exist yet), and nothing renders.

2. Using .data() Without a Key Function on Dynamic Data

When data changes order, elements get shuffled instead of updated in place.

// WRONG — elements may shuffle on re-render
selection.data(newData);

// RIGHT — stable identity tracking
selection.data(newData, function(d) { return d.id; });

3. Not Calling .exit().remove() on Updates

If you remove items from your data array but don’t call .exit().remove(), old DOM elements remain on screen — they just lose their data binding. Over time, stale elements accumulate.

4. Mixing D3 Version Syntax

D3 has gone through major API changes:

VersionScale SyntaxData Loading
v3d3.scale.linear()d3.csv() synchronous
v4+d3.scaleLinear()d3.csv() returns Promise
v5+Same as v4Uses fetch() internally
v7Same as v4/v5Latest refinements

Always check which version your CDN is loading and use the corresponding syntax.

5. Selecting Elements Before the DOM is Ready

// WRONG — script in <head>, #chart doesn't exist yet
d3.select("#chart").append("svg");

// RIGHT — wait for DOM
document.addEventListener("DOMContentLoaded", function() {
    d3.select("#chart").append("svg");
});

6. Forgetting that D3 Selects by Reference, Not Copy

When you chain .append(), the selection changes to the newly appended element:

var svg = d3.select("body").append("svg");  // svg = the <svg>
svg.append("circle");                         // appends inside the <svg>

This is intuitive once you know it, but beginners often expect .append() to return the original selection.

Practice Questions

Question 1

What does d3.select("p") return?

Answer: A D3 selection containing the first <p> element on the page. It’s not a raw DOM node — it’s a D3 selection object with chainable methods like .attr(), .style(), and .text().

Question 2

What is the difference between .enter() and .exit()?

Answer: .enter() provides references to data items that don’t have corresponding DOM elements yet — you use it to create new elements. .exit() provides references to DOM elements that no longer have corresponding data — you use it to remove elements.

Question 3

When would you use a key function with .data()?

Answer: When data has unique identifiers and can change order. The key function data(data, function(d) { return d.id; }) tells D3 to track elements by their identity, so elements update in place rather than reshuffling.

Question 4

What happens if you call .data([1,2,3]) on a selection of 5 elements?

Answer: Only 3 data items exist for 5 elements. The first 3 elements get data (update phase), and the remaining 2 elements go into the exit selection — you should call .exit().remove() to remove them.

Question 5

Can D3.js work with React?

Answer: Yes, but you must manage DOM ownership carefully. The common pattern is to let D3 manage an SVG element inside a React ref. D3 and React both want to control the DOM, so they need clearly separated responsibilities.

Challenge

Create a dynamic list that adds a new item every time a button is clicked. Use the enter-update-exit pattern to ensure items are properly managed. Start with an empty <ul> and data array []. Each click should add a random number to the array and re-render the list.

FAQ

What is the difference between D3.js and Chart.js?
Chart.js is a high-level charting library — you pass data and options and get a pre-built chart. D3.js is a low-level data-binding library — you build charts manually from SVG primitives. D3 gives total control but requires more code.
Do I need jQuery to use D3.js?
No. D3.js has its own selection engine. jQuery is not required and should not be used alongside D3 — they can conflict.
What version of D3 should I use?
Use D3 v7 (latest stable) for new projects. D3 v5 is still widely used in production. Avoid v3 for new work.
Can D3.js work with React or Vue?
Yes, but you must manage DOM ownership carefully. D3 and React/Vue both want to control the DOM. The common pattern is to let D3 manage an SVG element inside a React ref or Vue template ref.
What browsers does D3 support?
D3 v7 supports all modern browsers (Chrome, Firefox, Safari, Edge). IE is not supported in v5+.

Try It Yourself

Here’s a complete HTML document demonstrating the enter-update-exit pattern with a dynamic bar chart. Copy this into a file, open in your browser, and experiment:

<!DOCTYPE html>
<html>
<head>
    <title>Dynamic Data Join — Try It Yourself</title>
    <style>
        body { font-family: sans-serif; padding: 20px; }
        .bar { fill: #4CAF50; transition: fill 0.3s; }
        .bar:hover { fill: #FF9800; }
        .controls { margin: 10px 0; }
        button { padding: 8px 16px; margin: 0 4px; cursor: pointer; }
    </style>
</head>
<body>
    <h2>Dynamic Bar Chart — Try It Yourself</h2>
    <div class="controls">
        <button onclick="addData()">Add Bar</button>
        <button onclick="removeBar()">Remove Last</button>
        <button onclick="randomize()">Randomize</button>
        <button onclick="resetData()">Reset</button>
    </div>
    <svg width="400" height="200" id="chart"></svg>

    <script src="https://d3js.org/d3.v7.min.js"></script>
    <script>
        var data = [30, 60, 90, 50, 70];

        function render() {
            var svg = d3.select("#chart");
            var barWidth = 400 / Math.max(data.length, 1);
            var maxVal = d3.max(data) || 1;

            var bars = svg.selectAll("rect").data(data);

            // Exit: remove bars smoothly
            bars.exit()
                .transition().duration(300)
                .attr("height", 0).attr("y", 200)
                .remove();

            // Enter: create new bars
            var enter = bars.enter()
                .append("rect").attr("class", "bar")
                .attr("height", 0).attr("y", 200);

            // Enter + Update: position all bars
            bars = enter.merge(bars);
            bars.transition().duration(300)
                .attr("x", function(d, i) { return i * barWidth; })
                .attr("y", function(d) { return 200 - d * 200 / maxVal; })
                .attr("width", barWidth - 2)
                .attr("height", function(d) { return d * 200 / maxVal; });
        }

        function addData() {
            data.push(Math.floor(Math.random() * 100) + 10);
            render();
        }
        function removeBar() {
            if (data.length > 1) data.pop();
            render();
        }
        function randomize() {
            data = data.map(function() { return Math.floor(Math.random() * 100) + 10; });
            render();
        }
        function resetData() {
            data = [30, 60, 90, 50, 70];
            render();
        }
        render();
    </script>
</body>
</html>

Try this: Click “Add Bar” a few times, then “Remove Last”, then “Randomize”. Watch how the enter, update, and exit phases handle each change with smooth transitions.

What’s Next

Now that you understand D3.js basics, here’s where to go next:

TutorialWhat You’ll Learn
D3.js SVG — Shapes, Paths & TransformationsDraw circles, rectangles, paths, and use SVG groups
D3.js Scales & AxesMap data values to pixels with scales
D3.js Charts — Bar, Pie, Line & ScatterBuild complete charts from scratch

Related topics: JavaScript, React, SVG, CSS, HTML


Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro — bringing secure, high-performance software to your digital life.

What’s Next

Congratulations on completing this D3Js Basics tutorial! Here’s where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro