Skip to main content
Technology & EngineeringData Visualization146 lines

Chart Js

Expert guidance for building responsive charts quickly with Chart.js

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

## Key Points

- **Animations**: Customize via `options.animation` with duration, easing, and per-property configs.
- **Custom Plugins**: Write inline plugins using lifecycle hooks (`beforeDraw`, `afterDatasetsDraw`, etc.) to add annotations, watermarks, or custom drawing.
- **Interaction Modes**: Configure `options.interaction.mode` (nearest, index, dataset, point) for tooltip and hover behavior.
- **Responsive and Resizable**: Enabled by default; charts resize with their container.
- Always call `chart.destroy()` before creating a new chart on the same canvas to avoid memory leaks.
- Use tree-shaking by registering only the components you need rather than importing all registerables in production.
- Set `maintainAspectRatio: false` and control sizing via the parent container's CSS for predictable layout.
- Not destroying the previous chart instance before re-creating on the same canvas, which causes flickering and doubled renders.
- Setting `width` and `height` attributes directly on the canvas instead of using CSS on a wrapper div, which fights with the responsive resizing system.

## Quick Example

```bash
npm install chart.js
```

```js
import { Chart, registerables } from "chart.js";
Chart.register(...registerables);
```
skilldb get data-visualization-skills/Chart JsFull skill: 146 lines
Paste into your CLAUDE.md or agent config

Chart.js — Data Visualization

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

Overview

Chart.js is a simple, flexible JavaScript charting library that renders charts on an HTML5 Canvas element. It provides eight built-in chart types (bar, line, pie, doughnut, radar, polar area, bubble, scatter) with sensible defaults and extensive configuration. Use Chart.js when you need attractive, responsive charts with minimal setup and no dependency on SVG or the DOM.

Setup & Configuration

Install via npm:

npm install chart.js

Register components (tree-shakable in v4+):

import {
  Chart,
  CategoryScale,
  LinearScale,
  BarElement,
  BarController,
  Tooltip,
  Legend
} from "chart.js";

Chart.register(CategoryScale, LinearScale, BarElement, BarController, Tooltip, Legend);

Or register everything:

import { Chart, registerables } from "chart.js";
Chart.register(...registerables);

Create a chart:

<canvas id="myChart"></canvas>
const ctx = document.getElementById("myChart");
const chart = new Chart(ctx, {
  type: "bar",
  data: {
    labels: ["Jan", "Feb", "Mar", "Apr"],
    datasets: [{
      label: "Sales",
      data: [12, 19, 3, 5],
      backgroundColor: "rgba(54, 162, 235, 0.6)"
    }]
  },
  options: {
    responsive: true,
    plugins: {
      legend: { position: "top" }
    }
  }
});

Core Patterns

Multi-Dataset Charts

data: {
  labels: ["Q1", "Q2", "Q3", "Q4"],
  datasets: [
    { label: "2024", data: [65, 59, 80, 81], borderColor: "#3e95cd", fill: false },
    { label: "2025", data: [28, 48, 40, 19], borderColor: "#8e5ea2", fill: false }
  ]
}

Mixed Chart Types

const chart = new Chart(ctx, {
  type: "bar",
  data: {
    labels: ["Jan", "Feb", "Mar"],
    datasets: [
      { type: "line", label: "Trend", data: [10, 15, 12], borderColor: "red" },
      { label: "Volume", data: [20, 25, 18], backgroundColor: "steelblue" }
    ]
  }
});

Updating Data Dynamically

chart.data.datasets[0].data = [50, 60, 70, 80];
chart.update();

Advanced Features

  • Animations: Customize via options.animation with duration, easing, and per-property configs.
  • Custom Plugins: Write inline plugins using lifecycle hooks (beforeDraw, afterDatasetsDraw, etc.) to add annotations, watermarks, or custom drawing.
  • Interaction Modes: Configure options.interaction.mode (nearest, index, dataset, point) for tooltip and hover behavior.
  • Responsive and Resizable: Enabled by default; charts resize with their container.

Best Practices

  • Always call chart.destroy() before creating a new chart on the same canvas to avoid memory leaks.
  • Use tree-shaking by registering only the components you need rather than importing all registerables in production.
  • Set maintainAspectRatio: false and control sizing via the parent container's CSS for predictable layout.

Core Philosophy

Chart.js is designed around the principle that most charts should be easy. Its opinionated defaults -- responsive sizing, smooth animations, accessible colors -- mean that a basic bar or line chart looks good with minimal configuration. The library deliberately trades the infinite flexibility of SVG-based tools like D3 for speed of implementation on the Canvas element. When your goal is a well-understood chart type rendered quickly and attractively, Chart.js is the right tool. When you need a novel or highly custom visualization, it is not.

Canvas rendering gives Chart.js a performance edge for large datasets but imposes a fundamental constraint: chart elements are not DOM nodes. You cannot style bars with CSS, attach arbitrary event listeners to individual data points, or inspect elements in the browser dev tools the way you can with SVG-based libraries. Understanding this trade-off upfront prevents frustration. If your project requires deep interactivity or CSS-driven theming of individual chart elements, an SVG-based library is a better fit.

Treat chart lifecycle management as a first-class concern. A Chart.js instance holds references to the canvas, animation frames, and event listeners. Forgetting to destroy a chart before creating a new one on the same canvas is the most common source of bugs -- flickering, doubled renders, and memory leaks. In framework contexts like React or Vue, this means pairing chart creation with cleanup in the component lifecycle.

Anti-Patterns

  • Recreating without destroying: Calling new Chart(ctx, ...) on a canvas that already has a chart instance without calling chart.destroy() first. This causes two chart instances to fight over the same canvas, producing flickering and doubled event handlers.

  • Sizing the canvas directly instead of its container: Setting width and height attributes on the <canvas> element rather than sizing a wrapper <div> with CSS. This conflicts with Chart.js's responsive resizing system and produces unpredictable layout behavior.

  • Importing everything in production: Using Chart.register(...registerables) in a production bundle when only a bar chart is needed. This pulls in every chart type, scale, and plugin, inflating the bundle unnecessarily. Register only the components you use.

  • Mutating data without calling update: Changing the data array or options object directly and expecting the chart to reflect the changes. Chart.js requires an explicit chart.update() call after any mutation to trigger re-rendering and animation.

  • Over-animating dashboard charts: Using long animation durations on charts that update frequently (e.g., real-time dashboards). Each data update triggers a full animation cycle, causing the chart to perpetually animate and never settle into a readable state.

Common Pitfalls

  • Not destroying the previous chart instance before re-creating on the same canvas, which causes flickering and doubled renders.
  • Setting width and height attributes directly on the canvas instead of using CSS on a wrapper div, which fights with the responsive resizing system.

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

Get CLI access →