Integrating D3.js with Svelte

A practical guide to combining the power of D3.js for data visualization with the reactive and component-based architecture of Svelte 5.

6/22/2025

Why D3.js with Svelte?

D3.js is an incredibly powerful library for creating data-driven documents. It gives you fine-grained control over the DOM, allowing you to create complex and beautiful data visualizations. Svelte, on the other hand, excels at managing the DOM and state in a highly efficient, reactive way.

Combining them seems like a perfect match: Svelte manages the component’s state and structure, while D3 handles the complex parts of the visualization that are data-dependent.

A Simple Example

Let’s start with a basic example. We’ll create a Svelte component that uses D3 to draw and animate a simple circle inside an SVG element. The component below is fully self-contained. It uses Svelte’s $state for reactive properties and the $effect rune to interact with the DOM via D3 when those properties change.

This approach lets Svelte handle when to re-run the D3 code, keeping our logic clean and declarative.

This is a simple D3.js visualization rendered inside a Svelte component. Click the button to move the circle.

The code for the component above looks something like this:

// src/lib/components/blog/D3Circle.svelte
import { select } from 'd3-selection';
import 'd3-transition';

let svgEl: SVGElement | undefined = $state();

let cx = $state(50);
let fill = $state('#D4AF47');

$effect(() => {
    if (svgEl) {
        const svg = select(svgEl);
        const circle = svg.selectAll('circle').data([null]);
        const circleEnter = circle.enter().append('circle')
            .attr('r', 20)
            .attr('cy', 50);

        circle.merge(circleEnter)
            .transition()
            .duration(750)
            .attr('cx', cx)
            .attr('fill', fill);
    }
});

© 2025 Suvro Ghosh. All rights reserved.