Getting started
Observable Plot supports a variety of environments.
Try Plot online
The fastest way to get started (and get help) with Observable Plot is on Observable! Plot is available by default in notebooks as part of Observable’s standard library. To use Plot, simply return the generated plot from a cell like so:
Plot.rectY({length: 10000}, Plot.binX({y: "count"}, {x: d3.randomNormal()})).plot()
Observable includes a variety of Plot snippets when you click + to add a cell, as well as convenient sample datasets to try out Plot features. Or upload a CSV or JSON file to start playing with your data. You can even use Observable’s chart cell, which uses Plot’s auto mark under the hood, to create quick charts without writing code! You can then eject to JavaScript by clicking + to see the equivalent Plot code.
Plot in vanilla HTML
In vanilla HTML, you can load Plot from a CDN such as jsDelivr or you can download it locally. We recommend using the CDN-hosted ES module bundle as it automatically loads Plot’s dependency on D3. But for those who need it, we also provide a UMD bundle that exports the Plot global when loaded as a plain script.
<!DOCTYPE html>
<div id="myplot"></div>
<script type="module">
import * as Plot from "https://cdn.jsdelivr.net/npm/@observablehq/plot@0.6/+esm";
const plot = Plot.rectY({length: 10000}, Plot.binX({y: "count"}, {x: Math.random})).plot();
const div = document.querySelector("#myplot");
div.append(plot);
</script>
Plot returns a detached DOM element — either an SVG or HTML figure element. In vanilla web development, this means you need to insert the generated plot into the page to see it. Typically this is done by selecting a DOM element (such as a DIV with a unique identifier, like myplot above), and then calling element.append.
Installing from npm
If you’re developing a web application using Node, you can install Plot via pnpm, npm, yarn, or your preferred package manager.
pnpm add @observablehq/plot
npm install @observablehq/plot
yarn add @observablehq/plot
You can then load Plot into your app as:
import * as Plot from "@observablehq/plot";
Plot in React
We recommend two approaches for Plot in React depending on your needs.
The first is to server-side render (SSR) plots. This minimizes distracting reflow on page load, improving the user experience. For this approach, use the document plot option to tell Plot to render with React’s virtual DOM. For example, here is a PlotFigure component:
import * as Plot from "@observablehq/plot";
import {createElement as h} from "react";
export default function PlotFigure({options}) {
return Plot.plot({...options, document: new Document()}).toHyperScript();
}
Then, to use:
import * as Plot from "@observablehq/plot";
import PlotFigure from "./PlotFigure.js";
import penguins from "./penguins.json";
export default function App() {
return (
<div>
<h1>Penguins</h1>
<PlotFigure
options={{
marks: [
Plot.dot(penguins, {x: "culmen_length_mm", y: "culmen_depth_mm"})
]
}}
/>
</div>
);
}
}
Server-side rendering is only practical for simple plots of small data; complex plots, such as geographic maps or charts with thousands of elements, are better rendered on the client because the serialized SVG is large. For this second approach, use useRef to get a reference to a DOM element, and then useEffect to generate and insert your plot.
Plot in Vue
As with React, you can use either server- or client-side rendering with Plot and Vue.
For server-side rendering (SSR), use the document plot option to render to Vue’s virtual DOM. For example, here is a PlotFigure component:
import * as Plot from "@observablehq/plot";
import {h} from "vue";
export default {
props: {
options: Object
},
render() {
return Plot.plot({
...this.options,
document: new Document()
}).toHyperScript();
}
};
Then, to use:
<script setup>
import * as Plot from "@observablehq/plot";
import PlotFigure from "./components/PlotFigure.js";
import penguins from "./assets/penguins.json";
</script>
<template>
<h1>Plot + Vue</h1>
<PlotFigure
:options="{
marks: [
Plot.dot(penguins, {x: 'culmen_length_mm', y: 'culmen_depth_mm'}),
],
}"
/>
</template>
For client-side rendering, use a render function with a mounted lifecycle directive. After the component mounts, render the plot and then insert it into the page.
Plot in Svelte
Here’s an example of client-side rendering in Svelte:
<script lang="ts">
import * as Plot from '@observablehq/plot';
import * as d3 from 'd3';
let div: HTMLElement | undefined = $state();
let data = $state(d3.ticks(-2, 2, 200).map(Math.sin));
function onMousemove(event: MouseEvent) {
const [x, y] = d3.pointer(event);
data = data.slice(-200).concat(Math.atan2(x, y));
}
$effect(() => {
div?.firstChild?.remove(); // remove old chart, if any
div?.append(Plot.lineY(data).plot({ grid: true })); // add the new chart
});
</script>
<div onmousemove={onMousemove} bind:this={div} role="img"></div>
Plot in Node.js
You can use Plot to server-side render SVG or PNG in Node.js. Use JSDOM for a DOM implementation via the document option, then serialize the generated plot using outerHTML.
import {readFile} from "node:fs/promises";
import * as Plot from "@observablehq/plot";
import * as d3 from "d3";
import {JSDOM} from "jsdom";
const penguins = d3.csvParse(await readFile("./penguins.csv", "utf-8"), d3.autoType);
const plot = Plot.plot({
document: new JSDOM("{}").window.document,
marks: [
Plot.dot(penguins, {x: "culmen_length_mm", y: "culmen_depth_mm", stroke: "species"})
]
});
process.stdout.write(plot.outerHTML);