Skip to content
Guide

D3 charts in SvelteKit

D3 pairs well with Svelte when you keep it scoped to a single SVG and drive updates through resize events or reactive data. Treat D3 as a rendering layer, and let Svelte own the lifecycle.

Best practices

  • Initialize D3 only in onMount to avoid SSR mismatch errors.
  • Use ResizeObserver on the chart container to re-render on layout changes.
  • Read theme tokens from CSS variables so charts stay in sync with the shell.
  • Keep D3 updates idempotent: clear the SVG before re-rendering.
  • Pad your y-domain so the line never sits on the edges.
  • Cleanup observers and listeners on destroy to avoid leaks.

SvelteKit-friendly setup

<script lang="ts">
	import { onDestroy, onMount } from "svelte";
	import * as d3 from "d3";

	let svgEl;
	let wrapperEl;
	let resizeObserver;

	const data = Array.from({ length: 24 }, (_, index) => ({
		index,
		value: 0.6 + 0.2 * Math.sin(index / 2)
	}));

	const renderChart = () => {
		const width = Math.max(320, wrapperEl.getBoundingClientRect().width);
		const height = 260;
		const margin = { top: 24, right: 24, bottom: 36, left: 48 };

		const svg = d3.select(svgEl);
		svg.selectAll("*").remove();
		svg.attr("width", width).attr("height", height);

		const x = d3.scaleLinear().domain([0, data.length - 1]).range([margin.left, width - margin.right]);
		const y = d3.scaleLinear().domain([0, 1]).range([height - margin.bottom, margin.top]);

		const line = d3.line().x((d) => x(d.index)).y((d) => y(d.value));
		svg.append("path").datum(data).attr("fill", "none").attr("stroke", "currentColor").attr("d", line);
	};

	onMount(() => {
		renderChart();
		resizeObserver = new ResizeObserver(renderChart);
		resizeObserver.observe(wrapperEl);
	});

	onDestroy(() => {
		resizeObserver?.disconnect();
	});
</script>

Checklist

  • Container has a fixed height so SVG layout is stable.
  • Axes use tickSizeOuter(0) for clean endpoints.
  • Gridlines use low-contrast strokes so the data pops.
Built as a personal SvelteKit 5 lab with Supabase auth. Guides, patterns, and a playground you can actually ship.
Command Palette
Search for a command to run