Test store. Prices are the planned list prices stored as test data, license terms are drafts, and payments go to a Stripe test-mode account. No real money moves.

Canvas vs SVG vs DOM for HTML5 Games: Which One Should You Use?

Use canvas (2D or WebGL) for games with many moving objects, such as arcade, action and physics games. Use the DOM for turn-based games built from cards, tiles and text, where layout and accessibility matter more than frame rate. Use SVG for small vector scenes that must stay crisp at any size. Many production games combine them: a canvas for play, HTML for menus.

For HTML5 games, canvas vs SVG vs DOM is mostly a question of how many things move at once. Canvas redraws pixels every frame, so its cost depends on what you draw, not on how many objects exist, and it handles hundreds or thousands of sprites. SVG and the DOM keep every shape or element as a live object that the browser styles, lays out and hit-tests for you, which is convenient for a few dozen pieces and slow for thousands. Below we compare the three, show when each one wins, and cover the libraries that support each approach. For the canvas side in depth, see our HTML5 canvas games guide.

How each one draws

Canvas is immediate mode. You call drawing commands (fillRect, drawImage, or WebGL draw calls), the browser paints pixels into a bitmap, and nothing else is remembered. Your code keeps the game state and redraws the scene every frame. The browser has no idea that a cluster of pixels is "the player", so hit testing, layering and text layout are your job, or your engine's.

SVG and the DOM are retained mode. You create elements (<circle>, <div>, <button>), and the browser keeps them in a tree. Change an attribute or a style and the browser works out what to repaint. Each element gets events, CSS styling, accessibility information and hit testing for free. The price is per-element bookkeeping: style calculation, layout (for the DOM), and painting, all multiplied by the number of nodes you change.

The difference is like the one between a whiteboard and a corkboard. On the whiteboard you redraw everything, but redrawing a thousand dots is no harder than redrawing ten. On the corkboard each pinned card stays put and can be picked up, but moving a thousand cards every frame is a lot of handling.

Canvas vs SVG vs DOM at a glance

Canvas (2D or WebGL)SVGDOM (HTML and CSS)
Rendering modelImmediate: redraw pixels each frameRetained vector shapesRetained elements with CSS layout
Cost grows withPixels and draw callsNumber and complexity of shapesNumber of elements, style and layout work
Many moving objectsBestWeakWeak
Hit testingYou write it (or the engine does)Built in, per shapeBuilt in, per element
ScalingRedraw at the new size; handle pixel ratioCrisp at any sizeCrisp text and CSS; images need sizes
TextDrawn as pixels; you lay it outReal text, limited wrappingFull text layout, wrapping, right to left
AccessibilityNeeds extra work, often an HTML layerPossible with ARIA on elementsNative focus, keyboard and screen readers
AnimationYour game loopCSS, Web Animations API or scriptCSS transitions, Web Animations API
Typical gamesArcade, action, physics, platformers, 3DPuzzles, maps, diagrams, educational gamesCard, quiz, word, idle and board games

HTML5 game canvas vs DOM

The DOM is a better game engine than people expect for the right genre. Solitaire, a quiz, a word game, a clicker or a chess board are mostly rectangles with text that change a few times per second. Building them from HTML elements gives you real buttons with keyboard focus and screen reader labels, text that wraps and translates properly (including right-to-left languages), CSS for styling, and layout that adapts to any screen without writing a resize handler. Our free quiz game and card game code pages are good examples of game types that suit this approach.

The DOM falls behind once many things move every frame. Each change can trigger style recalculation and layout, and reading a layout property such as offsetTop right after writing a style forces the browser to do that work immediately. If you build a DOM game with motion, follow three rules:

  • Move elements with transform: translate() and fade them with opacity, which browsers can animate without re-running layout, instead of changing top, left, width or height.
  • Batch reads before writes in each frame, so the browser lays out the page once.
  • Keep the number of moving elements small, and recycle elements instead of creating and removing them constantly.

Canvas wins when the scene is busy: bullets, particles, scrolling tile maps, physics bodies, crowds. It also gives you full pixel control for effects that CSS can't express. What you give up is the free stuff: you write your own hit testing, your own UI widgets and your own text layout, and you have to add accessibility deliberately.

HTML5 games: canvas or SVG?

SVG's strength is that art stays crisp at every size and every pixel ratio, and that each shape is an object you can click, style and animate. A puzzle made of a few dozen pipe segments, a strategy map with clickable regions, a hidden-object scene of vector art, or an educational diagram where pieces snap into place are all natural SVG games. Files are small for flat vector art, and designers can export straight from their drawing tools.

The weakness is the same as the DOM's. Every shape is a node, complex paths and filters are expensive to repaint, and animating hundreds of shapes every frame is far more work for the browser than drawing them to a canvas. SVG also has none of the game structure a canvas engine gives you: no sprite batching, no camera, no physics.

A practical middle ground is to author vector art as SVG and render it into a canvas. An SVG file can be drawn with drawImage like any image, and engines can rasterize SVG at load time at the exact size you need. Phaser's loader has a this.load.svg() method that takes a width and height or a scale factor, and PixiJS v8 can load SVG as a texture or as vector Graphics, with a warning that complex shapes with holes may render inaccurately and that intricate SVGs are expensive to parse. You keep the crispness of vector art and the speed of a canvas renderer.

HTML5 SVG game tutorial: a clickable game in one file

This small SVG game shows what you get for free: the browser does the hit testing, the shapes scale with the window, and an animation fades each target out. Save it as svg-game.html and open it.

svg-game.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>SVG tap game</title>
  <style>
    body { margin: 0; background: #0f172a; }
    svg { display: block; width: 100vw; height: 100vh; touch-action: manipulation; }
  </style>
</head>
<body>
  <svg id="board" viewBox="0 0 400 300" preserveAspectRatio="xMidYMid meet">
    <text id="score" x="12" y="28" fill="#e2e8f0" font-size="20" font-family="sans-serif">Score: 0</text>
  </svg>
  <script>
    const NS = "http://www.w3.org/2000/svg";
    const board = document.getElementById("board");
    const scoreText = document.getElementById("score");
    let score = 0;

    function spawn() {
      const dot = document.createElementNS(NS, "circle");
      dot.setAttribute("cx", 30 + Math.random() * 340);
      dot.setAttribute("cy", 50 + Math.random() * 230);
      dot.setAttribute("r", 22);
      dot.setAttribute("fill", "#38bdf8");
      dot.addEventListener("pointerdown", () => { // the browser hit-tests the circle for us
        score += 1;
        scoreText.textContent = "Score: " + score;
        dot.remove();
      });
      board.appendChild(dot);
      // fade out over 1.8 s with the Web Animations API, then remove if nobody tapped it
      const fade = dot.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 1800, fill: "forwards" });
      fade.onfinish = () => dot.remove();
    }
    setInterval(spawn, 700);
  </script>
</body>
</html>

Notice what is missing compared with a canvas game: no resize handler (the viewBox scales everything), no pixel ratio code, no hit testing and no render loop. A spawn timer with setInterval is fine here because the browser, not your code, redraws the scene. Notice too what would hurt as the game grows: if each dot became a detailed illustration and there were 500 on screen, the browser would be managing 500 animated vector nodes. That is the point where you move to canvas.

HTML5 SVG game engines and vector engines

Few engines are built around SVG, and most "HTML5 vector game engine" searches end in one of these:

  • SVG.js describes itself as "the lightweight library for manipulating and animating SVG". It makes creating, moving and animating SVG shapes pleasant, but game structure (states, input mapping, collisions) is yours to write.
  • Two.js is a 2D drawing API that is renderer agnostic: the same code draws with SVG, Canvas or WebGL. You can start in SVG for easy debugging and inspection, then switch the renderer when object counts grow.
  • PixiJS and Phaser are canvas engines, but both import SVG art and both have vector Graphics objects for drawing shapes from code, rendered with WebGL.

For a game with many moving parts, the usual answer is a canvas engine with vector art imported at load time. If you are choosing between engines, our guide to HTML5 game sprites and animation explains how art reaches the renderer either way.

Mix them: canvas for play, HTML for menus

Few production games use only one of the three. A common setup is a canvas for the play area and its moving HUD, with HTML and CSS layered on top for menus, settings, dialogs, text input and long text. HTML gives those screens keyboard focus, accessibility and proper text layout, and the canvas gets to do what it does best. Phaser supports this directly with DOM elements placed over the game canvas.

Our 50 games all render their play area into a canvas: 41 through Phaser 4.2.1 and 9 through Three.js r186. Most of them ship in six languages, including Arabic with right-to-left layout, which is a strong argument for UI that measures and lays out its text rather than assuming fixed widths, whichever layer draws it.

If the game you are planning is busy and real-time, start with canvas and an engine. Our Phaser game source code shows complete Phaser 4 projects, and the performance guide covers how to keep a canvas game fast on phones.

Quick decision guide

  1. More than a few dozen objects move every frame? Canvas, usually with WebGL through an engine.
  2. Mostly cards, tiles, buttons and text that change on input? DOM.
  3. A small number of vector shapes that must stay sharp and clickable? SVG.
  4. 3D? WebGL or WebGPU on a canvas, through an engine such as Three.js.
  5. Unsure? Prototype the busiest screen of your game in each, and profile it on a mid-range phone.

Frequently asked questions

Is canvas faster than SVG for HTML5 games?

For scenes with many moving objects, yes. Canvas cost depends on the pixels and draw calls in each frame, while SVG cost grows with the number of shapes the browser has to track, restyle and repaint. For a few dozen mostly static shapes, SVG is fast enough and easier to work with.

Can you make a whole game with the DOM and no canvas?

Yes. Card, quiz, word, board and idle games work well as plain HTML and CSS, and they get keyboard access, screen reader support and text layout for free. Move elements with CSS transforms, and switch to canvas if the game needs many objects moving every frame.

Is there an HTML5 SVG game engine?

There are SVG libraries rather than full engines. SVG.js handles creating and animating shapes, and Two.js can draw the same scene with SVG, Canvas or WebGL. Canvas engines such as Phaser and PixiJS can load SVG art, which is the usual route for vector-style games.

Should game menus be drawn on the canvas or in HTML?

HTML is usually better for menus, settings and anything with a lot of text, because it brings focus handling, accessibility and proper text layout. Keep the in-game HUD on the canvas, where it moves with the play area.

We make and sell HTML5 game source code; links to our games are marked as ours.