← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Canvas API — 2D Drawing

JavaScript HTML5 Intermediate
debt(d7/e3/b5/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The common mistakes listed — missing beginPath(), wrong canvas sizing, devicePixelRatio issues — produce silent visual bugs (blurriness, unexpected fills, merged paths) that are invisible to compilers and linters. No detection_hints.tools are specified, and no standard linter rule catches these canvas-specific behavioral issues. They only surface when a developer visually inspects the rendered output or runs in a retina environment.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is a small pattern (ctx.save/ctx.restore wrapping), and the common_mistakes each have a targeted one-to-few-line fix: multiply dimensions by devicePixelRatio, add ctx.beginPath(), set width/height attributes instead of CSS, move computation out of requestAnimationFrame. No single fix is purely one-line since each requires locating all call sites and understanding context, so e3 rather than e1.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). Canvas API applies broadly to any web graphics work. Its global mutable context state (transforms, styles, path accumulation) means every developer touching canvas code must understand the stateful model, ctx.save/restore discipline, and sizing conventions. This is a persistent tax across all canvas-using components, but it doesn't reach into non-graphics parts of the codebase, keeping it from b7.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field explicitly states developers assume Canvas and SVG are interchangeable, which is a significant architectural wrong turn. Additionally, the stateful path model (beginPath() required) contradicts how most drawing APIs work, and CSS-based sizing silently producing a blurry bitmap contradicts standard web sizing conventions. Multiple documented gotchas contradict how similar web concepts behave elsewhere, warranting t7.

About DEBT scoring →

Also Known As

Canvas API HTML canvas 2D context CanvasRenderingContext2D

TL;DR

The HTML Canvas API provides a 2D drawing surface via JavaScript — used for charts, image manipulation, games, data visualisations, and any pixel-level rendering that DOM elements cannot efficiently handle.

Explanation

A <canvas> element provides a bitmap drawing surface. JavaScript obtains a 2D rendering context via canvas.getContext('2d') and draws using methods like fillRect(), arc(), drawImage(), and fillText(). Canvas is immediate mode — you draw commands execute immediately and the result is just pixels; there is no retained object graph like SVG. This makes Canvas fast for many operations but means you must redraw everything on each frame for animations. The CanvasRenderingContext2D API includes path drawing (beginPath, moveTo, lineTo, arc), fill and stroke styles (colours, gradients, patterns), text rendering, image compositing, and transformations (translate, rotate, scale). For 3D, use WebGL or WebGPU via getContext('webgl2') instead.

Watch Out

Canvas draws to a bitmap at the device pixel ratio, not CSS pixels — on high-DPI displays (e.g. Retina), you must manually scale the canvas width/height attributes and context to avoid blurry rendering, even though CSS styling might make it appear correct.

Common Misconception

Canvas and SVG are interchangeable. Canvas is pixel-based and immediate — good for many moving objects (games, particle systems). SVG is vector-based and retained — good for interactive diagrams with mouse events per element, accessibility, and scaling at any resolution. Choose based on the use case.

Why It Matters

Canvas is the foundation of chart libraries (Chart.js, D3 SVG/canvas modes), image editors, game engines (Phaser, PixiJS), and QR code generators in the browser. Understanding Canvas lets you implement custom visualisations that CSS and SVG cannot efficiently handle, and debug or optimise rendering in libraries that wrap it.

Common Mistakes

  • Not accounting for devicePixelRatio — canvas renders blurry on retina screens; multiply width/height by devicePixelRatio and scale the context.
  • Forgetting ctx.beginPath() before drawing paths — paths accumulate; without beginPath(), new shapes join the previous path, producing unexpected fills.
  • Setting canvas size with CSS instead of the width/height attributes — CSS scales the bitmap (blurry); the attributes set the actual resolution.
  • Doing heavy computation inside the animation loop — move data processing outside requestAnimationFrame and only draw inside it.

Avoid When

  • Building interactive diagrams or charts where you need clickable elements, tooltips, or accessibility — use SVG or DOM elements instead.
  • Creating scalable graphics that must render at multiple resolutions without pixelation — SVG is resolution-independent.
  • Rendering text-heavy documents or requiring complex text layout and selection — the DOM is better suited.
  • When you need automatic browser zooming or responsive scaling that works across device pixel ratios without manual management.

When To Use

  • You need to render charts, graphs, or data visualizations that update frequently and require pixel-perfect control without the overhead of DOM manipulation.
  • Building games or animations where you control every frame and need direct pixel access for collision detection, sprite rendering, or particle effects.
  • Performing real-time image manipulation (filters, transformations, compositing) on photos or video frames where SVG's vector approach is unsuitable.
  • Creating interactive drawing or annotation tools where immediate-mode rendering and low latency matter more than maintaining an editable object model.

Code Examples

✗ Vulnerable
// ❌ Leaking context state, not clearing between frames
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');

ctx.fillStyle = 'red'; // Never reset — affects all subsequent draws
ctx.translate(100, 100); // Cumulative! Each frame moves 100px further

function draw() {
    // Missing: ctx.clearRect(0, 0, canvas.width, canvas.height)
    ctx.fillRect(0, 0, 50, 50); // Draws over previous frame
    requestAnimationFrame(draw);
}
✓ Fixed
// ✅ Proper canvas animation loop
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');

let x = 0;

function draw() {
    // Clear the entire canvas each frame
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Save/restore to isolate state changes
    ctx.save();
    ctx.fillStyle = 'royalblue';
    ctx.translate(x, 100);
    ctx.fillRect(-25, -25, 50, 50); // Centred rect
    ctx.restore(); // fillStyle and translate are gone

    x = (x + 2) % canvas.width; // Loop across canvas
    requestAnimationFrame(draw);
}

// Set canvas resolution to match device pixel ratio (crisp on retina)
const dpr = window.devicePixelRatio || 1;
canvas.width  = canvas.offsetWidth  * dpr;
canvas.height = canvas.offsetHeight * dpr;
ctx.scale(dpr, dpr);

draw();

Added 23 Mar 2026
Edited 22 Jun 2026
Views 44
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 1 ping S 2 pings S 0 pings M 0 pings T 0 pings W 1 ping T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Amazonbot 9 Perplexity 5 Scrapy 4 Ahrefs 3 Google 2 Claude 2 SEMrush 2 ChatGPT 1 Majestic 1 Meta AI 1
crawler 28 crawler_json 2
DEV INTEL Tools & Severity
⚙ Fix effort: Medium
⚡ Quick Fix
Always call ctx.save() before and ctx.restore() after applying transformations or style changes you don't want to leak — the canvas context is global state.
📦 Applies To
javascript HTML5 web


✓ schema.org compliant