Canvas Coordinates
Canvas positions everything using a coordinate system where the origin (0,0) sits at the top-left corner, x grows rightward, and y grows downward.
The Canvas Coordinate System
Every drawing command on canvas takes coordinates measured in pixels from the canvas's origin, which is the top-left corner - not the bottom-left corner you might expect from a math class graph. The x-axis increases as you move right, exactly as you'd expect, but the y-axis increases as you move down the page. This matches how screens and images are typically addressed row by row from the top, so (0, 0) is always the top-left pixel and (canvas.width, canvas.height) is just past the bottom-right pixel.
Reading (x, y) Pairs
- fillRect(x, y, width, height) starts its top-left corner at (x, y) and grows right and down.
- moveTo(x, y) and lineTo(x, y) treat (x, y) as an exact pixel position, not a corner.
- Negative x or y values are valid - they simply place drawing off the visible canvas to the left or above.
- The bottom-right visible pixel of a canvas is at (width - 1, height - 1).
Example
<!DOCTYPE html>
<html>
<body>
<canvas id="grid" width="300" height="200" style="border:1px solid #ccc"></canvas>
<script>
const ctx = document.getElementById("grid").getContext("2d");
ctx.fillStyle = "crimson";
ctx.fillRect(0, 0, 10, 10);
ctx.fillStyle = "seagreen";
ctx.fillRect(290, 0, 10, 10);
ctx.fillStyle = "royalblue";
ctx.fillRect(0, 190, 10, 10);
ctx.fillStyle = "goldenrod";
ctx.fillRect(290, 190, 10, 10);
</script>
</body>
</html>Moving the Origin with translate()
ctx.translate(x, y) shifts where (0, 0) points for every drawing command that follows, without changing the canvas size. Instead of adding an offset to every coordinate in a repeating pattern, you can translate once and then draw using simple, local coordinates as if you were starting from a fresh origin.
Example
<!DOCTYPE html>
<html>
<body>
<canvas id="translated" width="300" height="150"></canvas>
<script>
const ctx = document.getElementById("translated").getContext("2d");
ctx.fillStyle = "slateblue";
ctx.fillRect(0, 0, 60, 60);
ctx.save();
ctx.translate(150, 50);
ctx.fillStyle = "tomato";
ctx.fillRect(0, 0, 60, 60);
ctx.restore();
</script>
</body>
</html>Example
<!DOCTYPE html>
<html>
<body>
<canvas id="axes" width="300" height="200"></canvas>
<script>
const ctx = document.getElementById("axes").getContext("2d");
ctx.strokeStyle = "#999";
for (let x = 0; x <= 300; x += 30) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, 200);
ctx.stroke();
}
for (let y = 0; y <= 200; y += 30) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(300, y);
ctx.stroke();
}
ctx.fillStyle = "black";
ctx.font = "12px sans-serif";
ctx.fillText("(0,0)", 2, 12);
ctx.fillText("(300,200)", 230, 195);
</script>
</body>
</html>Exercise: Canvas Coordinates
Where is the coordinate origin (0,0) located on an HTML canvas by default?