search

HTML Canvas for Beginners: A Complete Guide with Interactive Examples

The HTML <canvas> element gives you a pixel-level drawing surface directly in the browser. No plugins, no dependencies. If you have ever built a website but never touched Canvas, you are in the right place.

This guide walks you through the 2D Canvas API from the ground up, with interactive examples you can play with as you read. By the end you will know how to draw shapes, build paths, render text, animate particles, and manipulate image pixels.

Setting Up a Canvas

Every Canvas project starts with a <canvas> element and a rendering context. The element itself is just an empty rectangle. All the drawing happens through the 2D context object you get from getContext('2d').

<canvas id="myCanvas" width="600" height="360"></canvas>

<script>
  const canvas = document.getElementById('myCanvas');
  const ctx = canvas.getContext('2d');
</script>

Canvas sizing

A common mistake is sizing the canvas with CSS alone. CSS changes the display size but not the internal resolution, which produces blurry output. Always set width and height as element attributes. These define the actual pixel buffer.

For sharp rendering on Retina and HiDPI displays, multiply the buffer size by window.devicePixelRatio and then scale the context back down:

const dpr = window.devicePixelRatio || 1;
canvas.width  = 600 * dpr;
canvas.height = 360 * dpr;
canvas.style.width  = '600px';
canvas.style.height = '360px';
ctx.scale(dpr, dpr);

The coordinate system

Canvas uses a standard screen coordinate system. The origin (0, 0) is at the top-left corner. X increases to the right, Y increases downward. Hover over the canvas below to explore coordinates, and click to place marker dots.

Coordinate Explorer
x: 0, y: 0

Drawing Shapes

Canvas provides built-in methods for rectangles and circles. Rectangles are the only shape with direct methods. Everything else goes through the path API, which we will cover in the next section.

Rectangles

Three rectangle methods exist:

  • fillRect(x, y, width, height) draws a filled rectangle.
  • strokeRect(x, y, width, height) draws the outline.
  • clearRect(x, y, width, height) erases a rectangular area.

Circles and arcs

There is no circle() method. Instead you use arc(x, y, radius, startAngle, endAngle) inside a path. A full circle is an arc from 0 to Math.PI * 2.

ctx.beginPath();
ctx.arc(200, 150, 60, 0, Math.PI * 2);
ctx.fill();

Use the playground below to experiment with both shapes. Toggle between Rectangle and Circle, adjust the position, size, rotation, and shadow, and switch between Fill and Stroke modes.

Shape Playground
X 200
Y 100
Size 120
Rotation
Shadow 0px
Color #FFB42F

Paths and Lines

Paths are the foundation of complex Canvas drawing. A path is a list of points connected by line segments or curves. You start with beginPath(), add segments, and then fill or stroke the result.

The key methods are:

  • moveTo(x, y) lifts the pen and moves to a new starting point.
  • lineTo(x, y) draws a straight line from the current position.
  • quadraticCurveTo(cpx, cpy, x, y) draws a curve using a control point.
  • closePath() draws a line back to the starting point.
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(200, 50);
ctx.lineTo(200, 200);
ctx.closePath();
ctx.stroke();

Click on the canvas below to place points and watch the path form. Switch between straight lines and curves, and toggle the close-path option to see how closePath() works.

Path Builder

Colors and Gradients

Every fill and stroke operation uses the current fillStyle or strokeStyle. These accept any valid CSS color string. Canvas also supports linear and radial gradients as fill styles.

Linear gradients

A linear gradient is created with createLinearGradient(x1, y1, x2, y2). The four parameters define the start and end points of the gradient line. You then add color stops at positions between 0 and 1.

const grad = ctx.createLinearGradient(0, 0, 600, 0);
grad.addColorStop(0, '#FFB42F');
grad.addColorStop(0.5, '#840d32');
grad.addColorStop(1, '#2a5d8f');

ctx.fillStyle = grad;
ctx.fillRect(0, 0, 600, 360);

Radial gradients

createRadialGradient(x1, y1, r1, x2, y2, r2) defines two circles. The gradient radiates from the inner circle to the outer one. If both circles share the same center, you get a concentric effect.

Use the designer below to experiment with both gradient types. Adjust the angle or radius and pick different color stops to see how gradients work.

Gradient Designer
Angle 90°
Color Stops
Stop 1 #FFB42F 0%
Stop 2 #840d32 50%
Stop 3 #2a5d8f 100%

Text and Transformations

Canvas can render text directly onto the drawing surface using fillText() and strokeText(). You control the font, size, alignment, and baseline through context properties.

ctx.font = '32px sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Hello Canvas', 300, 180);

The transformation stack

Transformations let you move, rotate, and scale the entire coordinate system. The three core methods are translate(), rotate(), and scale(). Canvas applies them in the order you call them.

The critical pattern is save() and restore(). These methods push and pop the current state (transforms, styles, clipping) onto an internal stack. Without them, every transformation would accumulate and affect all subsequent drawing.

The golden rule: always wrap transforms in a save() / restore() pair. This keeps each drawing operation isolated and prevents transform leaks.

Try the demo below. Type your own text, adjust the font size, rotation, and scale to see how the transformation stack works. Toggle the Glow button for a neon shadow effect.

Text & Transforms
Font Size 36px
Rotation
Scale X 1.0
Scale Y 1.0
Color #FFB42F

Animation

Canvas does not animate on its own. You create animation by clearing the canvas and redrawing everything in a loop using requestAnimationFrame().

The basic pattern looks like this:

function animate(timestamp) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Update positions
    // Draw everything

    requestAnimationFrame(animate);
}

requestAnimationFrame(animate);

Delta time

For consistent animation speed across different refresh rates (60Hz, 120Hz, 144Hz), use delta time. This means calculating the time elapsed since the last frame and scaling all movement by that value. Without delta time, your animations will run faster on high-refresh-rate displays.

The particle system below demonstrates a full animation loop. Each particle has velocity, gravity, and a limited lifespan. Hover the canvas to repel particles away from your cursor.

Particle System
Particles 80
Speed 1.0x
Gravity 0.5
Size 4px

Image Manipulation

This is where Canvas truly separates itself from CSS and SVG. The getImageData() method gives you direct access to every pixel as an array of RGBA values. You can read, modify, and write back individual pixels to create filters and effects that would be impossible with CSS alone.

Drawing images

Use drawImage() to place an image onto the canvas. The image source can be an <img> element, another canvas, or a video frame.

const img = new Image();
img.src = 'photo.jpg';
img.onload = function() {
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
};

The pixel data API

Once the image is on the canvas, getImageData() returns an ImageData object containing a flat Uint8ClampedArray. Every four consecutive values represent one pixel: Red, Green, Blue, Alpha. For a 600×360 canvas, that is 864,000 values.

const imageData = ctx.getImageData(0, 0, w, h);
const data = imageData.data;

for (let i = 0; i < data.length; i += 4) {
    data[i]     = 255 - data[i];     // Invert Red
    data[i + 1] = 255 - data[i + 1]; // Invert Green
    data[i + 2] = 255 - data[i + 2]; // Invert Blue
    // data[i + 3] is Alpha, left unchanged
}

ctx.putImageData(imageData, 0, 0);

The photo editor below applies real-time pixel manipulation. Each slider modifies the pixel data through a different algorithm. The grayscale, sepia, and invert toggles show classic filter techniques. Pixelate demonstrates a spatial operation that groups pixels into blocks.

Note: This demo generates a sample landscape scene on the canvas. Hover the image to compare original vs filtered side by side.
Photo Editor
Hover the image to compare original vs filtered
Brightness 0
Contrast 0
Saturation 0
Pixelate 1px

Performance Tips

Canvas performance matters once you start animating or processing large amounts of pixel data. Here are the key practices that keep things smooth.

TechniqueWhat it doesWhen to use
Offscreen canvasPre-renders static content to a hidden canvas, then copies it with drawImage()Complex backgrounds, tiled patterns, cached text
Batch by styleGroups all shapes of the same color into one path before calling fill()Many same-colored shapes (particles, charts)
Avoid getImageData() in loopsReads the entire pixel buffer, which is slowCall once, process the array, write back once
requestAnimationFrameSyncs to the display refresh rateAlways use this instead of setInterval
Integer coordinatesPrevents sub-pixel anti-aliasing overheadPixel art, grids, UI elements

Avoid calling save() and restore() inside tight loops when you can manually reset only the properties you changed. And if part of your scene is static, render it once to a separate canvas and composite it with drawImage() each frame rather than redrawing everything.

FAQs

Common questions about working with the HTML Canvas element.

What is the difference between Canvas and SVG?
Canvas is pixel-based (rasterized). You draw onto a bitmap and the browser does not retain any knowledge of the shapes. SVG is vector-based and retains a DOM tree of elements you can style with CSS, animate, and attach event handlers to. Canvas is better for real-time rendering, games, and pixel manipulation. SVG is better for icons, charts with interactivity, and resolution-independent graphics.
How do I make a Canvas responsive?
Set the width and height attributes to your desired resolution, then use CSS max-width: 100% and height: auto on the canvas element. This scales the display without changing the drawing buffer. For dynamic resizing, listen for the resize event and update the buffer dimensions.
Does Canvas work on mobile browsers?
Yes. The 2D Canvas API has universal support across all modern mobile browsers including Chrome for Android, Safari on iOS, Firefox, and Samsung Internet. Touch events work the same as mouse events for interactive canvases. Be mindful of memory limits on mobile devices when working with large canvas buffers.
How do I handle Retina and HiDPI displays with Canvas?
Multiply the canvas width and height attributes by window.devicePixelRatio, set the CSS dimensions to the original size, and call ctx.scale(dpr, dpr). This gives you a higher-resolution drawing buffer while keeping the coordinate system in logical CSS pixels.
Can I use Canvas for production web applications?
Absolutely. Canvas powers production applications like Google Maps, Figma, and many browser-based games. For accessibility, provide fallback content inside the <canvas> tag and use ARIA attributes. For SEO, remember that text drawn on canvas is not indexable, so important content should be in the DOM.

Summary

The HTML Canvas API gives you direct control over every pixel on screen. Starting from basic shapes and paths, you can build up to gradients, text rendering, animation loops, and full image processing pipelines. The seven demos in this guide covered the core building blocks. From here, you can explore the full Canvas API on MDN for advanced topics like compositing, clipping paths, and the Path2D object.

Join the Discussion
0 Comments  ]

Leave a Comment

To add code, use the buttons below. For instance, click the PHP button to insert PHP code within the shortcode. If you notice any typos, please let us know!

Savvy WordPress Development official logo