---
title: "D3 Renderer"
description: "The D3 Renderer draws charts with D3, as SVG."
canonical_url: "https://tiptap-docs.lin52025i.qzz.io/diagrams/renderers/d3"
---

# D3 Renderer

The D3 Renderer draws charts with D3, as SVG.

## Quick start

```bash
npm install d3
```

```ts
import { d3Renderer } from '@tiptap-pro/extension-diagrams/d3'

Diagrams.configure({ renderers: [d3Renderer()] })
```

## Chart types

The D3 Renderer draws line, bar, area, scatter, pie, doughnut, radar, combo, tree and network
charts, and sankey charts with [`d3-sankey`](https://tiptap-docs.lin52025i.qzz.io/diagrams/renderers/d3.md#sankey-charts).

- **Network** is laid out by a force simulation. It runs a fixed number of steps from a fixed
  start, so the same data is drawn the same way every time.
- **`orientation: 'horizontal'`** lays the bars of a bar chart on their side. A combo chart keeps
  its bars upright.
- **Every field** of [series line styles](https://tiptap-docs.lin52025i.qzz.io/diagrams/charts/appearance.md#series-line-styles) and of
  [axes](https://tiptap-docs.lin52025i.qzz.io/diagrams/charts/axes.md), and [reference lines](https://tiptap-docs.lin52025i.qzz.io/diagrams/charts/references.md) are drawn.
- **A double click on a text** renames it, see [Editing in the chart](https://tiptap-docs.lin52025i.qzz.io/diagrams/charts/editing.md).

## Options

| Option           | Type                           | Description                                                                                                                                              |
| ---------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`             | `string`                       | The id charts store. Default `'d3'`                                                                                                                      |
| `label`          | `string`                       | The name for a menu. Default `'d3'`                                                                                                                      |
| `customizers`    | `Record<string, D3Customizer>` | Functions that change a drawn chart, by name. Default `{}`. See [Customizers](https://tiptap-docs.lin52025i.qzz.io/diagrams/renderers/d3.md#customizers) |
| `measureText`    | `(text, fontSize) => number`   | Returns a label's width, for exact label widths. Without it, widths are estimated                                                                        |
| `createDocument` | `() => Document`               | A `Document` for `toSVG` where there is no `document`, such as on a server                                                                               |
| `sankey`         | the `d3-sankey` module         | For sankey charts                                                                                                                                        |

## Sankey charts

```bash
npm install d3-sankey
```

```ts
import * as sankey from 'd3-sankey'

d3Renderer({ sankey })
```

Without `sankey`, the D3 Renderer does not list the `sankey` type, and another Renderer draws
sankey charts.

## Customizers

A customizer is a function you register under a name. A chart refers to it by that name:

```ts
d3Renderer({
  customizers: {
    highlightMax(svg, { data }) {
      // change the drawn SVG element: add marks, reorder, restyle
    },
  },
})

editor.commands.updateChartSpec({ spec: { renderer: { d3: { customizer: 'highlightMax' } } } })
```

The customizer receives the drawn `SVGSVGElement` and `{ data, spec, theme, size }`. It runs
after every draw, in the editor and in an export.

The document stores only the customizer's name, never its code. A chart that names a customizer
this editor does not have is drawn without one.

## Export and servers

In a browser, `toSVG` needs nothing else. On a server, pass a DOM implementation:

```ts
import { parseHTML } from 'linkedom'

d3Renderer({
  createDocument: () => parseHTML('<!doctype html><html><body></body></html>').document,
})
```
