HTML
HTML Canvas Graphics
The HTML <canvas>
element provides a drawable region on your web page, letting you render graphics dynamically with JavaScript. Whether you’re building data visualizations, games, or custom UI elements, the Canvas API gives you fine-grained control over pixels, shapes, text, and images.
Learning Outcomes
After completing this tutorial, you’ll be able to:
- Add and size a
<canvas>
element with fallback content. - Access the 2D context and draw shapes, paths, and text.
- Apply styles like fills, strokes, and gradients.
- Load and render images on the canvas.
- Use save/restore and transforms (translate, rotate, scale).
- Create simple animations with
requestAnimationFrame
and handle browser fallbacks.
Syntax & Setup
Begin by adding the <canvas>
element in your HTML:
<canvas
id="myCanvas"
width="600"
height="400"
style="border:1px solid #ccc;"
>
Your browser does not support the HTML <canvas> element.
</canvas>
id
: Lets your script find the canvas.width
/height
: Set the drawing area size in pixels.- CSS styling: Here we add a light border so you can see the canvas outline while developing.
What Is HTML Canvas?
The <canvas>
element is just an empty box in HTML. Nothing appears until you use JavaScript to draw into it. The Canvas API provides methods for:
- Paths (lines, curves)
- Shapes (rectangles, circles)
- Text (filled or stroked)
- Images (bitmaps or sprites)
- Gradients & Patterns
You control every pixel step by step, which makes Canvas perfect for animations, games, or dynamic charts.
The 2D Rendering Context
Before you can draw, you need to get the “context” object:
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
What this does:
getElementById
finds your<canvas>
by its id.getContext('2d')
returns an object (ctx
) with all the drawing methods and properties you’ll use.
Drawing Primitives
Rectangles
Method | Description | Signature |
---|---|---|
fillRect(x, y, w, h) |
Draws a filled rectangle. | (x, y, width, height) |
strokeRect(x, y, w, h) |
Draws only the rectangle’s outline. | (x, y, width, height) |
clearRect(x, y, w, h) |
Erases a rectangular area. | (x, y, width, height) |
Example:
<script>
const ctx = document.getElementById('myCanvas').getContext('2d');
// Light blue filled rectangle at (20,20), 150×100px
ctx.fillStyle = 'lightblue';
ctx.fillRect(20, 20, 150, 100);
// Navy border around a rectangle at (200,20)
ctx.lineWidth = 4;
ctx.strokeStyle = 'navy';
ctx.strokeRect(200, 20, 150, 100);
// Clear a smaller area (remove pixels) inside that rectangle
ctx.clearRect(230, 50, 80, 40);
</script>
How you’d use it:
- Choose
fillRect
to draw solid backgrounds or blocks.- Use
strokeRect
for frames or outlines.- Call
clearRect
when you need to “erase” part of the canvas (e.g., to animate or reset an area).
Paths (Lines & Curves)
Method | Description |
---|---|
beginPath() |
Start a new drawing path. |
moveTo(x, y) |
Move the pen to start without drawing. |
lineTo(x, y) |
Draw a straight line to the given point. |
bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y) |
Draw a cubic Bézier curve. |
quadraticCurveTo(cpx,cpy,x,y) |
Draw a quadratic curve (one control point). |
closePath() |
Connect the path back to its start point. |
stroke() / fill() |
Render the outline or fill the shape. |
Examples:
// 1) Simple filled triangle
ctx.beginPath();
ctx.moveTo(50, 200);
ctx.lineTo(150, 300);
ctx.lineTo(50, 300);
ctx.closePath();
ctx.fillStyle = 'tomato';
ctx.fill();
ctx.strokeStyle = 'black';
ctx.stroke();
What happens:
beginPath()
resets any existing path.moveTo
andlineTo
trace your triangle points.closePath()
completes it, then you fill and stroke to see it.
// 2) Cubic Bézier curve
ctx.beginPath();
ctx.moveTo(60, 350);
ctx.bezierCurveTo(100, 300, 200, 400, 250, 350);
ctx.strokeStyle = 'purple';
ctx.lineWidth = 3;
ctx.stroke();
Use case:
Perfect for smooth S-shaped curves or organic shapes—just tweak the four control points.
// 3) Quadratic curve
ctx.beginPath();
ctx.moveTo(60, 400);
ctx.quadraticCurveTo(150, 300, 300, 400);
ctx.strokeStyle = 'orange';
ctx.lineWidth = 4;
ctx.stroke();
When to pick:
For simpler curves with only one control point, like arches or gentle waves.
Text & Gradients
Filled Text
ctx.font = '24px sans-serif';
ctx.fillStyle = 'black';
ctx.fillText('Hello Canvas', 10, 50);
Tip:
font
sets the text size and family.fillText
draws solid text at (x, y).
Stroked Text
ctx.font = '24px sans-serif';
ctx.strokeStyle = 'red';
ctx.strokeText('Hello Canvas', 10, 100);
Why use it:
Creates outlined letters—great for contrast against busy backgrounds.
Linear Gradient
const linGrad = ctx.createLinearGradient(0, 0, 200, 0);
linGrad.addColorStop(0, 'red');
linGrad.addColorStop(1, 'yellow');
ctx.fillStyle = linGrad;
ctx.fillRect(10, 120, 200, 80);
How it works:
- Define gradient direction with two points.
- Use
addColorStop
to pick your colors.- Apply it like any
fillStyle
.
Radial Gradient
const radGrad = ctx.createRadialGradient(100, 250, 10, 100, 250, 80);
radGrad.addColorStop(0, 'blue');
radGrad.addColorStop(1, 'white');
ctx.fillStyle = radGrad;
ctx.fillRect(10, 220, 200, 80);
Use case:
Ideal for spotlight effects or circular fades.
Images
<img id="logo" src="logo.png" hidden>
<script>
const ctx = document.getElementById('myCanvas').getContext('2d');
const img = document.getElementById('logo');
img.onload = () => ctx.drawImage(img, 300, 20, 150, 100);
</script>
Practical tip:
- Hide your
<img>
in HTML.- Wait for
onload
so the image is fully available.drawImage
places and resizes it on the canvas.
Managing Canvas State
ctx.save();
ctx.translate(100, 100);
ctx.rotate(Math.PI / 4);
ctx.fillStyle = 'cyan';
ctx.fillRect(0, 0, 100, 100);
ctx.restore();
// After restore, transformations and styles reset
ctx.fillRect(150, 150, 100, 100);
Why it matters:
- Use
save()
before you transform or restyle.restore()
reverts everything back, so subsequent drawings aren’t affected.
Transforms
Translation
ctx.translate(50, 50);
Function: Moves the origin (0,0) by the given x,y. All future drawing shifts accordingly.
Rotation
ctx.rotate((45 * Math.PI) / 180);
Function: Rotates the canvas by radians around its origin.
Scaling
ctx.scale(2, 0.5);
Function: Stretches or shrinks everything drawn after it—here, twice as wide and half as tall.
Combined Transforms
ctx.translate(200, 50);
ctx.rotate(Math.PI / 6);
ctx.scale(1.5, 1);
ctx.fillStyle = 'lime';
ctx.fillRect(0, 0, 100, 50);
Order matters: Each transform builds on the last. Experiment in your console to see how changing the sequence alters the result.
Composition & Blending
ctx.globalCompositeOperation = 'multiply';
ctx.fillStyle = 'magenta';
ctx.fillRect(50, 50, 150, 150);
ctx.fillStyle = 'yellow';
ctx.fillRect(100, 100, 150, 150);
ctx.globalCompositeOperation = 'source-over'; // back to default
Use case:
Choose different composite modes (
multiply
,screen
,overlay
, etc.) for blend effects—just like in photo-editing software.
Animations
function animate(time) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(250, 150);
ctx.rotate((time / 1000) % (2 * Math.PI));
ctx.fillStyle = 'salmon';
ctx.fillRect(-25, -25, 50, 50);
ctx.restore();
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
How it works:
requestAnimationFrame
passes a timestamp toanimate
.- We clear the canvas each frame, then draw our rotating square.
- Looping
requestAnimationFrame
gives smooth, synced animations.
Browser Support
All modern browsers—including Chrome, Firefox, Safari, Edge, and Opera—natively support the HTML <canvas>
2D API. In older environments (such as Internet Explorer 8 and earlier), you may need a JavaScript-based polyfill or provide fallback content inside the <canvas>
tag to ensure your graphics still render.
FAQs on HTML Canvas Graphics
Can I draw 3D graphics with <canvas>
?
Yes—by using WebGL:
const gl = canvas.getContext('webgl');
How do I export my canvas as an image?
const dataURL = canvas.toDataURL('image/png');
Why does my canvas look blurry on high-DPI screens?
Increase its pixel dimensions (e.g., double width
/height
) and scale your drawing commands by 2.
How can I detect clicks on drawn shapes?
Listen for the canvas’s click
events, get the mouse coordinates (event.offsetX/Y
), then check if they fall within your shape’s area.
What’s the best way to optimize canvas performance?
- Batch your draws inside one
requestAnimationFrame
call - Cache static graphics in an offscreen canvas
- Minimize changing styles or transforms mid-draw