How We Compare
A comparison written by the authors of one of the libraries deserves some skepticism. Here's how we built these pages, so you can judge them, and check them.
Which libraries
We started from the most downloaded charting libraries on npm and rendered the ones that are free to use in a commercial product like Unovis:
| Library | Weekly downloads | License | Rendered here |
|---|---|---|---|
| Recharts | 57.4M | MIT | Yes |
| Chart.js | 12.7M | MIT | Yes |
| Apache ECharts | 5.7M | Apache-2.0 | Yes |
| Highcharts | 2.6M | Commercial | No: commercial use needs a paid license |
| ApexCharts | 2.0M | Dual license | No: the free license excludes companies above $2M in annual revenue and competing charting products |
| AG Charts | 1.8M | MIT (Community), commercial (Enterprise) | Yes, the Community edition |
| Nivo | 1.6M | MIT | Yes |
| Vega-Lite | 1.2M | BSD-3-Clause | Yes, through react-vega |
| Observable Plot | 0.7M | ISC | Yes |
| TanStack Charts | 0.5M | MIT | Yes |
| Unovis | 0.3M | Apache-2.0 | Yes |
Downloads are from npm for October 1–7, 2026, using @nivo/core for Nivo and ag-charts-community for AG Charts
(TanStack Charts: October 5–11, its first full week after 1.0).
D3 (22M weekly downloads) is a toolkit rather than a charting library; Unovis, Nivo and Observable Plot are built on
it. Plotly.js and Victory are popular too, and may join later.
The rules
- Same data, same chart. Every library draws the same data with the same series, axes, legend and tooltip.
- Idiomatic React. Each library uses its documented React integration. Observable Plot has no React component and its docs recommend mounting the plot in an effect, so that's what we do; Vega-Lite renders through react-vega, the Vega organization's wrapper around vega-embed. The code under Code is exactly the code that renders the chart next to it, and Show the data shows the data it gets.
- Default look. We kept each library's default colors, fonts and spacing. Recharts has no default color palette, so we used the colors from its documentation.
- Only what the chart needs. We turned off point markers where a library draws them by default, formatted axis values and tooltips, and turned on shared tooltips where a library has them.
- Legend toggles. Where a library doesn't hide series from its legend on its own (Unovis, Recharts and Observable Plot), we added the few lines of state it takes. TanStack Charts' interactive legend is controlled, so its demos keep the visible series in state too, and filter the hidden rows themselves where the legend doesn't (the polar charts and the network graph).
- Dark mode. Each chart follows the site theme the way its library documents it: built-in dark themes for ECharts,
AG Charts and Vega-Lite (vega-embed's
darktheme), colors passed in for Chart.js, Recharts and Nivo, and a background color for Observable Plot, whose text and axes followcurrentColor. Unovis and TanStack Charts need no code for it. - Free editions. AG Charts is used in its free Community edition. Features that need AG Charts Enterprise are marked Paid edition.
- Plugins where a chart needs one. When a library can only draw a chart with a plugin, we used the most popular one: chartjs-chart-graph, chartjs-chart-sankey and chartjs-chart-geo for Chart.js. The presets also use the Chart.js team's own plugins: chartjs-plugin-annotation for bands and reference lines and chartjs-plugin-datalabels for data labels. A library that can't draw a chart at all, or only in a paid edition, gets a placeholder with the reason and a source.
- Presets. Every page has preset buttons that reconfigure all the charts at once, to show options beyond the default chart. Each library draws a preset with its own documented options. Where it has no option for one, its card keeps the default chart under a note that says what's missing, with a source.
Feature research
Every cell in the feature tables was checked against the library's type definitions and source code for the version listed below, and against its official documentation. Where the docs and the code disagreed, we ran the code. Every cell links to its source.
Bundle size
We bundled the same chart with every library: a line chart with three smooth (monotone) lines, x and y axes, a legend, a tooltip showing all series, a crosshair at the hovered x and animation, which is what a Unovis line chart does out of the box. Each library draws it with its own options, its React integration and tree-shaken imports wherever it supports them. Where a library can't do part of it, we measured it without that part: Observable Plot and Vega-Lite have no animation, AG Charts Community has neither the crosshair nor animation (both are Enterprise modules), and Nivo animates data updates but not the first render. Chart.js has no crosshair option, so its bundle includes the usual few-line plugin that draws one.
Each library was installed on its own from a lockfile, bundled with esbuild (--bundle --minify --format=esm --target=es2020, production mode, React and ReactDOM external) and checked in a browser to make sure the chart rendered,
animated and drew its crosshair. A second bundler, Rollup, gave sizes within about 3 KB gzipped and the same ranking,
except that Chart.js and TanStack Charts, 0.3 KB apart there, swap places. Unovis is measured from the build in this
repository, the same package a release publishes, so the numbers describe the version these pages document; the other
libraries are the published packages at the versions listed below.
| Library | What was bundled | Minified | Gzipped |
|---|---|---|---|
| Unovis | @unovis/react, built from this repository | 163.0 KB | 52.4 KB |
| TanStack Charts | @tanstack/charts/react/core with the motion() renderer, d3Curve(curveMonotoneX) and focusGuideX | 161.3 KB | 54.7 KB |
| Chart.js | react-chartjs-2 + chart.js, registered components only, and a few-line crosshair plugin | 162.1 KB | 56.8 KB |
| Observable Plot | @observablehq/plot in a useEffect, with a pointer rule as the crosshair; Plot doesn't animate | 262.4 KB | 88.8 KB |
| Nivo | @nivo/line, with slices as the crosshair | 270.5 KB | 93.6 KB |
| Recharts | recharts | 372.0 KB | 108.9 KB |
| ECharts | echarts-for-react/lib/core + echarts/core, registered components only | 538.1 KB | 182.8 KB |
| Vega-Lite | react-vega + vega-embed, vega-lite and vega, with a rule as the crosshair; Vega-Lite doesn't animate | 825.4 KB | 284.5 KB |
| AG Charts | ag-charts-react + ag-charts-community, registered modules only; the crosshair and animation are Enterprise | 1320.8 KB | 397.0 KB |
TanStack Charts is where the configuration matters most. Its defaults draw straight lines with no crosshair and no
animation: 106.8 KB minified / 37.5 KB gzipped. The measured chart adds d3Curve(curveMonotoneX), focusGuideX and the
motion() renderer, which animates the first render and data updates as Unovis does. Animating only data updates, with
the svgAnimation option instead of motion(), gives 118.2 / 41.3 KB. The harness keeps both as reference builds.
React and ReactDOM add another 44.8 KB gzipped if your app doesn't ship them already. None of the libraries needs a separate stylesheet. AG Charts requires registering the modules a chart uses, but registering fewer modules barely changes its bundle size.
Versions tested
| Library | Packages | Version | Default renderer |
|---|---|---|---|
| Unovis | @unovis/react | 1.8.0 | SVG |
| Recharts | recharts | 3.10.1 | SVG |
| Chart.js | chart.js, react-chartjs-2, chartjs-chart-graph, chartjs-chart-sankey, chartjs-chart-geo, chartjs-chart-matrix, chartjs-chart-treemap, @sgratzl/chartjs-chart-boxplot, chartjs-plugin-annotation, chartjs-plugin-datalabels | 4.5.1 | Canvas |
| ECharts | echarts, echarts-for-react | 6.1.0 | Canvas |
| Nivo | @nivo/line, @nivo/bar, @nivo/scatterplot, @nivo/pie, @nivo/network, @nivo/sankey, @nivo/geo, @nivo/heatmap, @nivo/treemap, @nivo/chord, @nivo/boxplot, @nivo/sunburst, @nivo/radial-bar | 0.99.0 | SVG |
| AG Charts | ag-charts-community, ag-charts-react | 14.2.0 | Canvas |
| Observable Plot | @observablehq/plot | 0.6.17 | SVG |
| Vega-Lite | vega-lite, vega, vega-embed, react-vega | 6.5.0 | SVG |
| TanStack Charts | @tanstack/charts | 1.1.0 | SVG |
Found a mistake?
Libraries change quickly, and we'd like these pages to stay accurate. If something is wrong or out of date, open an issue and we'll fix it.
Last updated in October 2026.