Articles

Canvas vs SVG: Choosing the Right Graphics API

Canvas draws immediate-mode pixels you redraw yourself; SVG keeps a live, styleable DOM of vector shapes. Here's how to pick between the two.

Takina Takina · · 4 min read
HTML and CSS code displayed on a screen

Canvas and SVG are the web platform’s two native graphics APIs, and they take opposite approaches: canvas is an immediate-mode bitmap you draw onto with JavaScript calls, with no memory of what you drew after the fact, while SVG is a retained-mode format — a tree of vector shape elements that lives in the DOM, stays styleable with CSS, and stays inspectable like any other markup.

How canvas works: immediate mode

A <canvas> element is a blank rectangular bitmap. You get a drawing context — typically 2d or webgl — and issue imperative calls to paint pixels onto it: fillRect, arc, drawImage, and so on. Once a shape is drawn, the canvas has no idea it was ever a “circle” or a “rectangle” — it’s just pixels. If you want to move that circle, you don’t update an object; you clear the canvas (or the affected region) and redraw everything from your own application state.

This makes canvas well suited to scenes with large numbers of elements that change every frame — games, particle effects, real-time data visualizations, image manipulation — because the browser never has to track a DOM node per shape. The cost is that you own all the bookkeeping: hit-testing (figuring out what the user clicked), accessibility, and redraw logic are all your responsibility.

How SVG works: retained-mode DOM

An SVG document is markup: <circle>, <rect>, <path>, and other elements form a tree just like HTML does, and that tree lives in the DOM. Each shape is a real element you can select, style with CSS, animate with CSS transitions, and attach event listeners to directly — clicking a <circle> fires a click event on that specific element, no manual hit-testing required.

Because shapes remain addressable elements, updating one is as simple as changing an attribute or a CSS property; the browser handles repainting just the affected region. This retained structure is also what makes SVG resolution-independent — as vector paths rather than a fixed pixel grid, an SVG icon or illustration scales cleanly to any size without blurring.

Canvas vs SVG

CanvasSVG
ModelImmediate mode (bitmap)Retained mode (DOM tree)
ScalingPixelatesResolution-independent
Per-shape eventsManual hit-testingNative DOM events
StylingDraw calls onlyCSS-stylable
Best forThousands of changing objects, pixel effectsIcons, diagrams, charts, illustrations
AccessibilityManual (ARIA on the canvas element)Native (each shape is inspectable markup)
DOM costOne element totalOne element per shape

Performance: many objects vs few

The performance line between the two comes down to element count and update frequency. SVG performs well with hundreds of shapes that update occasionally, because the browser’s rendering pipeline is optimized for DOM diffing and repaint of small regions. Once you’re pushing thousands of shapes that all move every animation frame — think a particle system or a real-time chart streaming updates dozens of times a second — maintaining that many DOM nodes becomes the bottleneck, and canvas’s flat bitmap model, paired with requestAnimationFrame for scheduling redraws, scales better because there’s no per-shape DOM overhead to pay.

For genuinely GPU-bound workloads — 3D scenes, shader effects — neither 2D API is the right tool; that’s what WebGPU and WebGL exist for, both of which render into a canvas element but bypass its 2D drawing API entirely.

Accessibility and styling differences

Because SVG shapes are real DOM elements, they participate in accessibility trees, can carry role and aria-label attributes per shape, and follow normal focus and keyboard-navigation rules if you wire up tab order — much of the same thinking behind semantic HTML applies directly to SVG markup. Canvas content is invisible to assistive technology by default; a screen reader sees an empty rectangle unless you explicitly duplicate the drawn content as an accessible fallback, following the same accessibility practices you’d apply anywhere else images or graphics carry meaning.

Styling follows the same split: SVG shapes take CSS properties like fill, stroke, and opacity directly and can be themed with the same stylesheet as the rest of your page, including dark-mode overrides. Canvas has no CSS hooks into what’s drawn — every visual property is a JavaScript argument passed at draw time.

Which to pick

Default to SVG for anything that’s fundamentally a diagram: icons, logos, charts with a moderate number of data points, illustrations, and interactive graphics where individual elements need their own click handlers or accessible labels. Reach for canvas when you’re rendering large or rapidly changing scenes where per-element DOM overhead would be the bottleneck, or when you’re doing pixel-level image processing that has no natural representation as discrete shapes.

The takeaway

Canvas and SVG solve the same category of problem — drawing graphics in the browser — from opposite ends: canvas is a bitmap you paint imperatively and must redraw yourself, while SVG is a live, stylable, accessible DOM tree of vector shapes the browser manages for you. Pick SVG when shapes need to stay addressable, styleable, and accessible; pick canvas when you’re pushing enough moving pixels that per-element DOM bookkeeping becomes the bottleneck.

Takina Takina · · 4 min read

Svelte 5 Runes Explained

Svelte 5 runes like $state and $derived replace the old reactive-assignment magic with explicit function calls that work anywhere in a file.

#JavaScript #Frameworks #Web Development
Takina Takina · · 4 min read

Shallow Copy vs Deep Copy in JavaScript

A shallow copy duplicates an object's top-level properties but shares nested references; a deep copy duplicates everything recursively. How to do each.

#JavaScript #Web Development #Frontend