Skip to main content
Technology & EngineeringData Visualization152 lines

Plotly

Expert guidance for building interactive, publication-quality charts with Plotly.js

Quick Summary26 lines
You are an expert in creating data visualizations with Plotly.js.

## Key Points

- **3D Charts**: Use `type: "scatter3d"`, `type: "surface"`, or `type: "mesh3d"` for three-dimensional visualizations rendered with WebGL.
- **Mapbox and Geo Maps**: Use `type: "scattermapbox"` or `type: "choropleth"` for geographic plots.
- **Animations**: Use `Plotly.animate()` with frame definitions to create animated transitions between data states.
- **Custom Modebar**: Configure the toolbar buttons with `config: { modeBarButtonsToRemove: [...], displaylogo: false }`.
- **Click and Selection Events**: Listen to `plotly_click`, `plotly_selected`, and `plotly_hover` events for interactivity.
- Use `Plotly.react()` instead of `Plotly.newPlot()` for updates; it efficiently diffs and re-renders only what changed.
- Use partial bundle imports (`plotly.js-basic-dist-min`, `plotly.js-cartesian-dist-min`) to reduce bundle size when you only need specific chart types.
- Set `layout.autosize: true` and pass `{responsive: true}` in the config for charts that resize with their container.
- Importing the full `plotly.js` bundle (over 3 MB minified) instead of a partial bundle, which dramatically inflates the application size.
- Not using `Plotly.purge()` or `Plotly.react()` when updating, leading to memory leaks from orphaned chart instances.

## Quick Example

```bash
npm install plotly.js-dist-min
```

```html
<script src="https://cdn.plot.ly/plotly-2.35.0.min.js"></script>
```
skilldb get data-visualization-skills/PlotlyFull skill: 152 lines
Paste into your CLAUDE.md or agent config

Plotly.js — Data Visualization

You are an expert in creating data visualizations with Plotly.js.

Overview

Plotly.js is a high-level, declarative charting library built on D3.js and WebGL. It supports over 40 chart types including statistical charts (box plots, violin plots, histograms), 3D charts, geographic maps, and scientific visualizations. Charts are interactive by default with zoom, pan, hover, and export capabilities. Use Plotly.js when you need publication-quality, interactive charts with rich statistical or scientific chart types.

Setup & Configuration

Install via npm:

npm install plotly.js-dist-min

Or use the CDN:

<script src="https://cdn.plot.ly/plotly-2.35.0.min.js"></script>

Basic usage:

import Plotly from "plotly.js-dist-min";

Plotly.newPlot("chart", [
  {
    x: ["Jan", "Feb", "Mar", "Apr"],
    y: [10, 15, 13, 17],
    type: "scatter",
    mode: "lines+markers",
    name: "Revenue"
  }
], {
  title: "Monthly Revenue",
  xaxis: { title: "Month" },
  yaxis: { title: "Revenue ($K)" }
});

React Integration

npm install react-plotly.js plotly.js-dist-min
import Plot from "react-plotly.js";

function MyChart() {
  return (
    <Plot
      data={[{ x: [1, 2, 3], y: [2, 6, 3], type: "scatter", mode: "lines" }]}
      layout={{ title: "My Chart", autosize: true }}
      useResizeHandler={true}
      style={{ width: "100%", height: "400px" }}
    />
  );
}

Core Patterns

Bar Charts

Plotly.newPlot("chart", [
  { x: ["A", "B", "C"], y: [20, 14, 23], type: "bar", name: "2024" },
  { x: ["A", "B", "C"], y: [12, 18, 29], type: "bar", name: "2025" }
], {
  barmode: "group"
});

Statistical Charts

// Box plot
Plotly.newPlot("chart", [
  { y: [1, 2, 3, 4, 5, 6, 7, 8, 9], type: "box", name: "Group A" },
  { y: [2, 3, 3, 4, 5, 5, 6, 7, 10], type: "box", name: "Group B" }
]);

Subplots

Plotly.newPlot("chart", [
  { x: [1, 2, 3], y: [4, 5, 6], xaxis: "x", yaxis: "y" },
  { x: [1, 2, 3], y: [6, 5, 4], xaxis: "x2", yaxis: "y2" }
], {
  grid: { rows: 1, columns: 2, pattern: "independent" }
});

Updating Charts

// Efficient update without full re-render
Plotly.react("chart", newData, newLayout);

// Extend existing traces with new data points
Plotly.extendTraces("chart", { y: [[newValue]] }, [0]);

Advanced Features

  • 3D Charts: Use type: "scatter3d", type: "surface", or type: "mesh3d" for three-dimensional visualizations rendered with WebGL.
  • Mapbox and Geo Maps: Use type: "scattermapbox" or type: "choropleth" for geographic plots.
  • Animations: Use Plotly.animate() with frame definitions to create animated transitions between data states.
  • Custom Modebar: Configure the toolbar buttons with config: { modeBarButtonsToRemove: [...], displaylogo: false }.
  • Click and Selection Events: Listen to plotly_click, plotly_selected, and plotly_hover events for interactivity.

Best Practices

  • Use Plotly.react() instead of Plotly.newPlot() for updates; it efficiently diffs and re-renders only what changed.
  • Use partial bundle imports (plotly.js-basic-dist-min, plotly.js-cartesian-dist-min) to reduce bundle size when you only need specific chart types.
  • Set layout.autosize: true and pass {responsive: true} in the config for charts that resize with their container.

Core Philosophy

Plotly is built on the premise that charts should be interactive by default. Zoom, pan, hover tooltips, and export are not features you add -- they are features you would have to explicitly remove. This philosophy makes Plotly the natural choice when the audience needs to explore the data rather than passively view a static image. If your chart will be embedded in a report or printed on paper, Plotly's interactivity is overhead; if it will be viewed in a browser by someone asking their own questions, it is an accelerant.

The declarative data-and-layout model separates what you are showing (traces in the data array) from how it is presented (the layout object). This separation matters because it means you can swap chart types, add traces, or change layout properties without restructuring your code. It also enables efficient updates via Plotly.react(), which diffs the new specification against the current state and only re-renders what changed. Treating the specification as an immutable description and using Plotly.react() for updates is the correct mental model.

Bundle size is a real engineering concern. The full Plotly.js bundle exceeds 3 MB minified. For applications that only need a bar chart and a line chart, the partial bundles (plotly.js-basic-dist-min, plotly.js-cartesian-dist-min) are dramatically smaller. Choosing the right bundle is not premature optimization; it is a deployment requirement for any performance-sensitive web application.

Anti-Patterns

  • Importing the full Plotly bundle for simple charts: Using plotly.js-dist or plotly.js-dist-min (3+ MB) when only cartesian chart types are needed. The partial bundles cut the size by 60-80% with no loss of functionality for common chart types.

  • Using newPlot for every update: Calling Plotly.newPlot() on every data change instead of Plotly.react(). newPlot tears down and rebuilds the entire chart, losing zoom state, selection state, and causing a visible flash. react() performs an efficient diff and preserves interaction state.

  • Not calling Plotly.purge() on removal: Removing the chart's container div from the DOM without calling Plotly.purge() first. This leaks event listeners, animation frames, and WebGL contexts, especially problematic in single-page applications with frequent navigation.

  • Hardcoding dimensions instead of using responsive mode: Setting fixed width and height in the layout rather than using layout.autosize: true with config.responsive: true. Fixed dimensions break on different screen sizes and require manual recalculation on container resize.

  • Overloading a single chart with too many traces: Adding dozens of traces to one chart without filtering, grouping, or using subplots. Beyond 10-15 overlapping traces, the chart becomes unreadable and interaction performance degrades. Use faceted subplots or a dropdown filter to manage complexity.

Common Pitfalls

  • Importing the full plotly.js bundle (over 3 MB minified) instead of a partial bundle, which dramatically inflates the application size.
  • Not using Plotly.purge() or Plotly.react() when updating, leading to memory leaks from orphaned chart instances.

Install this skill directly: skilldb add data-visualization-skills

Get CLI access →