A blank rectangle, and code that paints on it
← Back to Web CodingA <canvas> is a blank patch of page. HTML gives you the patch; it cannot draw a single thing on it. Everything you see on a canvas was put there by JavaScript — which means every picture is a program.
Two steps to get started, and they are the same two every time:
<canvas id="board" width="300" height="160"></canvas>
<script>
const canvas = document.getElementById("board");
const ctx = canvas.getContext("2d");
ctx.fillStyle = "crimson";
ctx.fillRect(20, 20, 120, 80);
</script>
Try it — this is live
getElementById finds the canvas — same as Lesson 6.getContext("2d") hands you the brush. Everybody calls it ctx.A canvas has no edge of its own — it is completely invisible until you draw. The faint dashed grey line round every canvas in these lessons is put there by the page, just so you can see where the edges are. It is not part of the picture and you never have to draw it.
On a page of your own you would add a real one yourself with CSS: <canvas style="border:2px solid #333">.
width="300" height="160" as attributes sets how many pixels the canvas has. Setting it in CSS instead stretches those pixels like a blown-up photo, and everything goes blurry.
Top-left. And y grows downwards — this trips up everyone who did coordinates in maths class.
const ctx = document.getElementById("board").getContext("2d");
ctx.fillStyle = "#1a5490";
ctx.fillRect(0, 0, 40, 40);
ctx.fillStyle = "seagreen";
ctx.fillRect(120, 0, 40, 40);
ctx.fillStyle = "darkorange";
ctx.fillRect(0, 100, 40, 40);
ctx.fillStyle = "#111";
ctx.font = "13px monospace";
ctx.fillText("(0,0) is up here", 50, 25);
ctx.fillText("bigger y = further DOWN", 50, 125);
Try it — this is live
No centimetres, no percentages. (120, 40) means 120 pixels across from the left edge and 40 pixels down from the top.
Three commands, and all four numbers mean the same thing every time: x, y, width, height.
const ctx = document.getElementById("board").getContext("2d");
ctx.fillStyle = "#4a90d9";
ctx.fillRect(20, 20, 90, 60);
ctx.strokeStyle = "crimson";
ctx.lineWidth = 4;
ctx.strokeRect(130, 20, 90, 60);
ctx.fillStyle = "gold";
ctx.fillRect(20, 110, 200, 60);
ctx.clearRect(60, 130, 60, 30);
Try it — this is live
| Command | What it does |
|---|---|
ctx.fillRect(x, y, w, h) | a solid rectangle |
ctx.strokeRect(x, y, w, h) | just the outline |
ctx.clearRect(x, y, w, h) | rubs that patch out |
ctx.fillStyle = "…" | the colour fills use |
ctx.strokeStyle = "…" | the colour outlines use |
ctx.lineWidth = 4 | how thick outlines are |
Notice the pattern: fillStyle and lineWidth are settings you change, and they stay changed until you change them again. fillRect is an action. Set the paint, then paint.
A line is not one command — it is a little journey. Start a path, move the pen, draw to somewhere, then say what to do with it.
const ctx = document.getElementById("board").getContext("2d");
ctx.strokeStyle = "#1a5490";
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(30, 30);
ctx.lineTo(270, 30);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(30, 70);
ctx.lineTo(150, 200);
ctx.lineTo(270, 70);
ctx.closePath();
ctx.stroke();
Try it — this is live
beginPath() — forget the last shape, start freshmoveTo(x, y) — lift the pen and put it herelineTo(x, y) — draw from where the pen is to hereclosePath() — draw back to where the path startedstroke() — actually ink it. Or fill() to colour it in.Leave it out and the new shape joins on to the old one — and every stroke() redraws everything in the path, so old lines get thicker and change colour. If your drawing is mysteriously all one colour, this is why.
const ctx = document.getElementById("board").getContext("2d");
ctx.fillStyle = "#1a5490";
ctx.font = "bold 30px sans-serif";
ctx.fillText("Hello!", 20, 50);
ctx.font = "16px monospace";
ctx.fillStyle = "seagreen";
ctx.fillText("small and green", 20, 90);
ctx.strokeStyle = "crimson";
ctx.lineWidth = 1;
ctx.strokeText("outlined", 20, 130);
Try it — this is live
The y you give fillText is the baseline — the line the letters stand on, not their top. Ask for y = 0 and the text is above the canvas where nobody can see it.
<canvas width height> makes the patch; JavaScript does all the drawing.const ctx = canvas.getContext("2d") — every drawing starts here.fillStyle) stay set; actions (fillRect) happen once.beginPath → moveTo → lineTo → stroke.