Chartist

Search

Find a guide, an API entry or an example.

Try

Open source · MIT or WTFPL · since 2014

Simple charts, dressed in CSS.

Chartist draws clean, responsive SVG charts and leaves the styling to you. No canvas, no dependencies, no theme engine. Just classes and custom properties.

// npm install chartist@next
import { lineChart } from 'chartist';
import 'chartist/styles.css';

lineChart('#chart', { series: [[1, 3, 2, 5]] });

520k npm downloads a month13.4k GitHub starsused by 72.8k repositories

Quietly running a lot of the web's charts

From npm and GitHub · October 14, 2026
520knpm downloads in the last month
72.8kpublic repositories depend on it
13.4kstars on GitHub
12 yearsof charts in production, since 2014

1 / 5Draw a line in one line

Chapter 1

Draw a line in one line

Give it a container and some numbers. Labels, grid, scaling and responsiveness are handled; the styling is yours.

import { lineChart } from 'chartist';

lineChart('#chart', {
  labels: ['Mon', 'Tue', 'Wed'],
  series: [[5, 9, 7], [3, 4, 6]]
});
Chapter 2

Bars, side by side or stacked

Same data shape, different function. Group series per label, or stack them to show totals.

import { barChart } from 'chartist';

barChart('#chart', {
  labels: ['Q1', 'Q2', 'Q3', 'Q4'],
  series: [[5, 4, 3, 7], [3, 2, 9, 5]]
}, { stackBars: false });
Chapter 3

Donuts, pies and gauges

Slices are SVG paths with classes, so a donut sweep is just a stroke animation in CSS.

import { pieChart } from 'chartist';

pieChart('#chart', { series: [40, 30, 20, 10] }, {
  donut: true,
  donutWidth: 20
});
Chapter 4

Compose bars and lines

Layer bars and lines in one chart, each with its own Y axis on the left or right.

import {
  chart, cartesianAxes, stepAxis, autoScaleAxis, bar, line, axisLabels
} from 'chartist';

const days = ['Mon', 'Tue', 'Wed', 'Thu'];
chart('#chart', {
  data: {
    labels: days,
    series: [
      { name: 'orders', data: [4, 6, 5, 8] },
      { name: 'growth', data: [20, 45, 38, 60] }
    ]
  },
  axes: cartesianAxes([
    { id: 'days', side: 'bottom', type: stepAxis(), ticks: days },
    { id: 'orders', side: 'left', type: autoScaleAxis() },
    { id: 'growth', side: 'right', type: autoScaleAxis() }
  ]),
  layers: [
    bar({ series: ['orders'], y: 'orders' }),
    line({ series: ['growth'], y: 'growth', align: 'center' }),
    axisLabels()
  ]
});
Chapter 5

That's the tour

Four chart shapes, one way of styling them: CSS. Keep scrolling for what makes it worth it.

// That's the tour.
// Keep scrolling for the details.

What makes it worth it

The things people pick Chartist for, each with a tiny live demo.

Style it with CSS

Plain SVG with predictable classes. Pick a color:

--ct-series-a

Responsive, two ways

By the window, or by the chart's own container (experimental), with the conditions you write in CSS.

responsive([
  ['(width < 600px)', small],
  [container('(width < 400px)'), tiny]
])

Composed charts

Bars and lines in one chart, each on its own Y axis.

Renders anywhere SVG does

Real SVG text labels. Render on the server for PDFs, email and images.

renderToString(toScene(config, size))

Tiny, and no build step

You ship only what you import. A CDN module or npm, your pick.

  • ✓ core (chart)4.4 kB
  • ✓ core + lineChart12.4 kB
  • ✗ barChartnot imported
  • ✗ pieChartnot imported

Extend everything

Every element passes through an open pipeline. Change, replace or decorate any of it in a few lines, or pick a community plugin.

chart.on('compose', node =>
  node.role === 'point'
    ? node.addClass('ct-hot')
    : node
);
See the pipeline ↓
And also:Typed functional APIZero dependencies1.x code keeps workingColor-blind-safe palette

Bend it to your will

Every chart flows through an open pipeline. Each phase has an event, and every single element passes through compose, where you can change, replace or decorate it. Plugins use the same events.

  1. 01Resolveon('resolve')
  2. 02Prepareon('prepare')
  3. 03Layouton('layout')
  4. 04Composeon('compose')
  5. 05Sceneon('scene')
  6. 06Renderon('render')
  7. 07Mounton('mount')
Same data, three tiny plugins
/** Lollipop bars: a dot on each bar; CSS makes the stick thin. */
export const lollipop = (): ChartPlugin => ({
  name: 'lollipop',
  install(chart) {
    chart.on('compose', series => {
      if (series.role !== 'series') {
        return;
      }
      return decorateBars(series.addClass('ct-lollipops'), bar => {
        const { x2, y2, style } = bar.attrs;
        return node('circle', { cx: x2, cy: y2, r: 6, style }, 'ct-lollipop');
      });
    });
  }
});
/* style.css */
.ct-lollipops .ct-bar { stroke-width: 3px; }

Community plugins add tooltips, legends, axis titles and zoom; plugins written for 1.x run in v2 through fromLegacyPlugin.

Edit it. Watch it redraw.

Every example in the docs is live. Change the data or the CSS and the chart updates as you type, right in the page. No sandbox site, no bundler.

src/main.ts
import 'chartist/styles.css';
import { lineChart } from 'chartist';

lineChart(
  '#chart',
  {
    labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
    series: [
      [12, 9, 7, 8, 5],
      [2, 1, 3.5, 7, 3]
    ]
  },
  { fullWidth: true, chartPadding: { right: 30 } }
);
Live

Responsive sugar topping

Grab the corner and squeeze the chart. The labels rearrange themselves, driven by the same conditions you'd write in CSS.

Resize me520 px
responsiveactive: container(width ≥ 520px)
barChart('#chart', data, options, [
  [container('(width >= 520px)'), {
    axisX: { labelInterpolationFnc: month }    // "Jan"
  }],
  [container('(360px <= width < 520px)'), {
    axisX: { labelInterpolationFnc: initial }  // "J"
  }],
  [container('(width < 360px)'), {
    axisX: { labelInterpolationFnc: quarter }  // "Q1"
  }]
]);
Experimental: container() needs the match-container polyfill today

One chart, two cards

The same chart in a narrow and a wide card. Container queries pick the right options for each, no matter how wide the window is.

width < 260px
width < 260px

Animations, in plain CSS (and a little SMIL)

Lines draw, bars grow, donuts sweep, and a SMIL line morphs for fun. All of it calms down for people who prefer reduced motion.

Lines draw in.ct-line { animation: ct-draw }
Bars grow.ct-bar { animation: ct-draw }
Donuts sweep.ct-slice-donut { animation: ct-draw }
SMIL morph<animate attributeName="d">

How Chartist compares

An honest look next to Chart.js, ApexCharts and Highcharts. They're excellent libraries; pick the one that fits the job.

Chartist compared with Chart.js, ApexCharts and Highcharts
Measured on October 14, 2026ChartistChart.jsApexChartsHighcharts
Bundle sizea line chart, minified and gzipped12.4 kBthis build49.4 kBv4.5.1154.9 kBv7.6.1104.7 kBv13.1.1
RenderingSVGCanvasSVG (canvas renderer opt-in)SVG
Styling with CSScolors, lines and text from your stylesheetYes, classes and custom propertiesNo, options in JavaScript (canvas)Mostly options in JavaScriptYes, in styled mode
No build stepload it from a CDN in a plain HTML pageYes, native ES moduleYes, script tagYes, script tagYes, script tag
Server-side renderingYes, to an SVG string, no DOMNot built inYes, apexcharts/ssrYes, export server (headless browser)
TypeScript typesYes, written in TypeScriptYes, bundledYes, bundledYes, bundled
License for commercial useFree (MIT or WTFPL)Free (MIT)Free under $2M revenue, paid abovePaid license
Chart typesLine, area, scatter, bar, pie, donut, gauge, composed8 types plus mixed charts25+ typesDozens, plus Stock, Maps and Gantt
Tooltips and zoomThrough pluginsTooltips built in, zoom pluginBuilt inBuilt in
Sources
Where Chartist shines

Small bundles, plain SVG, styling with the CSS you already write, ES modules straight from a CDN with no build step, and a permissive license.

Where others offer more

More chart types out of the box, and built-in interactivity like tooltips, zoom and panning. If you need a full dashboard toolkit, they're great choices.

How we measured

One line chart with the smallest setup each library documents (Chart.js tree-shaken registration, ApexCharts core plus the line type, Highcharts’ recommended import), bundled with esbuild (minified, ESM, browser) and gzipped (level 9). Versions: Chart.js 4.5.1, ApexCharts 7.6.1, Highcharts 13.1.1. Feature and license rows come from each library's own documentation, listed under Sources. Last run October 14, 2026. Spotted something out of date? Open an issue.

Fits whatever you build with

Framework-free, so it works everywhere. Community wrappers make it feel native in your stack.

Made by a community since 2014

92 contributors have shaped Chartist since 2014. Questions, ideas and pull requests are all welcome.

Hats off
  • Gion Kunz
  • Dan Onoshko
  • Hannes Kamecke
  • autarc
  • Paul Salaets
  • jwatmuff
  • Ivan Tsenilov
  • Alex
  • Daniel Diekmeier
  • Tyler Gaw

From the first commit in 2014 to v2: the creator, the maintainers and everyone who sent a pull request. Read the credits

Ready when you are.

One import, one function call, one chart. He's already celebrating.

npm install chartist@next