The SVG-versus-canvas choice for charts is not about which renderer is faster. It is about how many marks you draw, whether users interact with individual data points, and whether the chart has to be accessible. Get those three right and the "performance" debate mostly disappears.

Here is the short version. SVG draws every mark as a real DOM element, which makes each one crisp, styleable, hoverable, and readable by assistive technology, at the cost of one node per mark. Canvas draws everything into a single bitmap, which stays fast no matter how many marks you draw, at the cost of having nothing inside to inspect, style, or announce. Neither is universally better.

Key takeaways

  • The choice is decided by data density and interaction, not a raw speed benchmark. For most dashboards, either renderer is fine.
  • SVG cost depends on the mark type, not just the point count. A 5,000-point line is a single <path>. A 5,000-point scatter is 5,000 nodes. This is the nuance most comparisons miss.
  • SVG wins on interactivity, styling, crisp export, and accessibility. Each mark is a real element you can target.
  • Canvas wins on raw mark count. Tens of thousands of points, or a screen full of many charts, favor a single bitmap per chart.
  • A rough SVG ceiling is a few thousand individual marks per chart. Past that, reduce the data, switch the mark type, or move to canvas or WebGL.

See the difference for yourself

The demo below renders the same dataset two ways. The SVG chart (ApexCharts) and the canvas chart draw identical data. Change the point count and the mark type, and watch the DOM node count of each, measured live in your browser.

Points:
Draw as:
SVG (ApexCharts)
DOM nodes in the chart: measuring...
Canvas (hand-drawn)
DOM nodes in the chart: 1

Switch to Points at 5,000 and watch the SVG node count. Every point is a real element you can style, hit-test, and expose to assistive technology, which is the whole tradeoff. Switch to Line and the SVG count barely moves: a line is a single <path> no matter how many points feed it. The canvas stays at one node in every case, and pays for it in inspectability.

Two things to notice. At 5,000 points drawn as individual points, the SVG chart holds thousands of DOM nodes while the canvas holds one. Switch to a line and the SVG count collapses, because a line is one path regardless of how many points define it. That single behavior explains most of the practical differences below.

What SVG and canvas actually are

SVG (Scalable Vector Graphics) is a markup language. Every shape is an element in the DOM, like <rect>, <circle>, or <path>, with attributes you can read and change. A chart drawn in SVG is a live document you can query, style with CSS, attach event listeners to, and hand to a screen reader.

Canvas is a bitmap you paint with a drawing API. context.fillRect(...) sets pixels. Once painted, the browser has no idea a "bar" exists; there is only color. To change anything, you clear and redraw. To know which bar the user clicked, you calculate it yourself from the coordinates.

That difference, a tree of elements versus a flat image, is the root of every tradeoff that follows.

The comparison

DimensionSVGCanvasEdge
Rendering modelOne DOM element per markOne bitmap for everythingDepends
Crispness on zoom and retinaVector, resolution-independentRaster, must redraw at device pixel ratio to stay sharpSVG
Per-element stylingCSS and attributes, per markManual redraw of the whole sceneSVG
InteractivityNative DOM events per markManual hit-testing from coordinatesSVG
AccessibilityElements can carry roles, names, titlesOpaque bitmap, needs a separate text alternativeSVG
Text qualityCrisp DOM textRasterized with the sceneSVG
Export and printClean vector outputRaster imageSVG
Cost at high mark countGrows with node countFlat, one bitmapCanvas
Memory at high mark countGrows with node countRoughly constantCanvas
Many charts on one screenNode counts add up fastCheap per chartCanvas

The pattern is clear: SVG wins nearly every quality and interaction dimension, and canvas wins the two that matter at scale. Your data volume decides which column you are living in.

What actually matters

Mark type, not just point count

The most common mistake is treating "lots of data" as automatically bad for SVG. It depends on how you draw it.

  • A line or area is a single <path> element. Feeding it 200 points or 20,000 points changes the path data, not the node count. SVG handles this comfortably.
  • Individual marks (scatter points, bars, candlesticks) are one element each. Here the node count tracks the data, and SVG cost climbs with it.

So "SVG vs canvas at 10,000 points" has two different answers. As a line: SVG is fine. As a scatter: measure it, and probably reach for canvas or thin the data.

Interactivity is close to free in SVG

Because every mark is an element, a tooltip on hover, a click handler on a bar, or a CSS highlight on the hovered slice is a native event and a style change. In canvas you rebuild that yourself: track the pointer, map its position back to a data point, and redraw. For charts where users poke at individual values, SVG removes a whole category of code.

Accessibility is not a tie

A canvas chart is a single image with no internal structure, so a screen reader gets nothing unless you add a text alternative by hand. SVG elements can carry roles, names, and descriptions. We measured this across ten libraries in our charting accessibility audit: the canvas-based libraries shipped no accessible semantics by default. If accessibility matters to you, SVG starts from a much better place. Note that "can be accessible" still requires the library, or you, to add the semantics.

Canvas earns its place at scale

None of this makes canvas the weaker choice. When you genuinely have tens of thousands of marks, or a wall of sparklines, canvas keeps a flat cost while SVG drowns the DOM in nodes. That is a real ceiling, not a theoretical one, and it is exactly when the bitmap model pays off.

What about WebGL?

For the extreme end, hundreds of thousands of points or heavy real-time streams, there is a third option. WebGL renders on the GPU and scales far past canvas. It is more complex to work with and shares canvas's opacity to the DOM, so it is a specialist tool, not a default. Some libraries expose it for specific chart types (for example a GPU scatter mode) while keeping SVG or canvas for everything else. Reach for it only when canvas itself is the bottleneck.

How to choose

Use data density and interaction needs as the deciding factors. These thresholds are starting points, not hard limits, so measure on your target device.

Your situationUse
Fewer than about 1,000 marksSVG. Crisp, interactive, accessible, and the cost is irrelevant.
Lines or areas, any realistic point countSVG. One path scales fine.
Dense scatter or bars in the low thousandsMeasure. SVG often still holds; thin the data if it does not.
Tens of thousands of individual marksCanvas, or downsample first. Nobody reads 50,000 points.
Many charts on one screen (sparkline grids)Canvas per chart, or a lightweight renderer.
Per-point interaction, custom styling, or accessibilitySVG.
Print or high-resolution exportSVG, for vector output.

When not to use canvas: if your data is small and you need interaction, accessibility, or crisp export, canvas costs you all of that for a performance win you do not need.

When not to use SVG: a 50,000-point real-time scatter will bury the DOM. That is canvas or WebGL territory, or a sign to aggregate the data before charting it.

Which libraries use which

Knowing a library's renderer tells you its ceiling and its defaults in advance.

RendererLibraries
SVGApexCharts, Highcharts, Recharts, Chartist, Google Charts, D3 (typically)
CanvasChart.js, ECharts (default; also offers an SVG renderer), amCharts 5
WebGLPlotly (GL trace types), deck.gl, and other GPU-first tools

ApexCharts is SVG-based, which is why it leans into crisp rendering, per-element interaction, and accessible output. For the data volumes most dashboards actually show, hundreds to low thousands of points, that is the right tradeoff. When a specific view needs far more, that is the moment to switch renderers for that view, not to abandon the approach everywhere.

FAQ

Is canvas always faster than SVG for charts? No. Canvas has a flat cost regardless of mark count, so it wins at high data density. But for a line or area chart, or any chart under a few thousand marks, SVG performs fine and gives you interactivity and accessibility that canvas does not.

Why does my SVG chart slow down with a lot of data? Because individual marks each become a DOM node, and thousands of nodes are expensive to lay out and paint. If the chart is a line or area, this should not happen, since that is a single path. If it is a scatter or bar chart, reduce the point count, aggregate, or switch to canvas.

Which is better for accessibility, SVG or canvas? SVG. Its elements can carry ARIA roles, names, and descriptions, so a screen reader can announce the chart. A canvas is one opaque bitmap and needs a separate text alternative that you add yourself. See our accessibility audit for measured results.

Does SVG look sharper than canvas? SVG is resolution-independent, so it stays crisp at any zoom and on any display automatically. Canvas is a raster and must be drawn at the device pixel ratio to avoid looking soft on high-density screens.

What should I use for real-time streaming charts? It depends on volume. A live line chart is fine in SVG. A high-frequency scatter with tens of thousands of points wants canvas or WebGL, or an aggregation step before rendering.

Summary

SVG versus canvas is a data-density and interaction decision, not a speed contest. SVG gives you crisp, interactive, accessible, exportable charts, and its only real cost is one DOM node per mark, which matters solely when you draw thousands of individual marks. Canvas gives you a flat cost at any scale, and pays for it with an opaque bitmap that you cannot style, target, or announce without extra work. For the point counts most dashboards show, SVG is the stronger default, and the moment a specific view outgrows it, switch that view to canvas or WebGL rather than compromising everywhere. Decide by counting your marks and asking whether users touch them, then pick the renderer that fits.