The HTML <canvas> element enables you to create all kinds of graphics using JavaScript code. Have you ever used a bitmap drawing program like Microsoft Paint? Well, canvas is kinda the same thing, except you draw programmatically instead of clicking and dragging with your mouse.

This makes canvas tag a really easy to create images that update dynamically - for example graphs and charts, animations, or games.

In this post, we'll walk through the basics of canvas, and how to get started with it. Let's go!

Creating a HTML canvas element

You create your canvas like this:

<canvas id="drawing" width="400" height="300"></canvas>

You can choose any size you want, of course, but if you don't specify a width and height here, the canvas will take a default size of width="300" and height="150". Interestingly, you can also specify a size in the CSS too:

#drawing {
width: 400px;
height: 300px;
margin: 10px;
border: 4px solid #000;
border-radius: 15px;
background-color: #fff;
}

Why do we need to specify width and height in two places? I'll answer this question later on - it will be easier to explain once we've done some drawing.

The above code gives us a simple, blank canvas:

See the Pen on CodePen.

Now let's start drawing on it!

Context is key - especially with canvas

As explained earlier, you draw on the canvas using JavaScript code. There are two key variables you need for this:

let drawing = document.getElementById("drawing");
let c = drawing.getContext("2d");

The drawing variable is a pointer to our canvas element. You can call this whatever you like.

The c element is called the context, and it's basically your paintbrush. The context contains all of the methods you need to use whenever you draw something on the canvas. A lot of people name this variable ctx, but I prefer c simply because it's less typing (you'll be using it a lot).

Now, if you were sat in front of a real canvas, with your paintbrush in hand, what's the first thing you'd do? You'd dip it in some paint, obviously! And it's the same with our HTML canvas - the context has a property for that. In fact, it has two - strokeStyle, which sets the colour of any lines or paths you draw, and fillStyle which sets the fill colour:

c.fillStyle="hotpink";
c.strokeStyle="#000";
c.lineWidth=2;

Drawing simple shapes on the HTML canvas

Now that we've set the context properties, we can use one of canvas's drawing methods! Let's start with a simple rectangle:

See the Pen on CodePen.

To create this, just use the code below:

c.rect(50, 50, 300, 200);
c.fill();
c.stroke();

So rect defines the rectangle, stroke draws the line/border, and fill fills it in with the colour you wanted.

The first two arguments in rect are the starting coordinates - in this case x=50, y=50. The second two arguments are the width and height of the rectangle - 300px by 200px.

Important note: The coordinate system in canvas is flipped vertically from what you're used to in normal graphs!

So the top left of the canvas area is x=0, y=0. As you move down the canvas, your y value increases. That means the x=50, y=50 starting coordinates of the above rectangle refers to its top left corner.

Choose your path wisely!

OK, now imagine that you want to draw not one, but two rectangles. And not only that, but you want each one to be a different colour (we're really getting fancy now!).

You might think, "No problem. I'll just use rect to define another rectangle, then use stroke() and fill() to draw it. Simple." Something like this, maybe:

c.fillStyle="hotpink";
c.strokeStyle="#000";
c.lineWidth=2;

c.rect(50, 50, 100, 200);
c.fill();
c.stroke();

c.fillStyle="#7DF9FF";

c.rect(250, 50, 100, 200);
c.fill();
c.stroke();

Well, not so fast there buddy - that won't actually work. This is what the above code will produce:

See the Pen on CodePen.

You wanted one rectangle in hot pink, and the other in electric blue, but they are both blue. Why?

It's because they are part of the same path. You can think of a path as a series of instructions that the canvas API will follow step-by-step. After you created the first rectangle, you updated fillStyle, and then called fill() again. But because the two rectangles are in the same path, the fill() was applied to both.

To fix this, you must use c.beginPath(), and c.closePath(), like this:

c.beginPath();
c.fillStyle="hotpink";
c.strokeStyle="#000";
c.lineWidth=2;
c.rect(50, 50, 100, 200);
c.fill();
c.stroke();
c.closePath();

c.beginPath();
c.fillStyle="#7DF9FF";
c.strokeStyle="#000";
c.lineWidth=2;
c.rect(250, 50, 100, 200);
c.fill();
c.stroke();
c.closePath();

This gives us the different colours we wanted:

See the Pen on CodePen.

Note that technically you only need to put the rect part within the path - but I just find the code is much more readable if you put everything inside - then you know which styles belong to which shape.

Drawing your own shapes on the canvas

In canvas you have a huge range of methods you can employ in your drawings, but you only have two basic shapes - a rectangle, which you've already seen, and a simple line which you can use to draw your own shapes.

To draw lines, you use c.moveTo(x, y) to move to a particular set of coordinates, and c.lineTo(x, y) to draw a line from that point. You can then use c.stroke() and c.fill() as normal.

So to draw a triangle you could use this:

c.beginPath();
c.fillStyle="hotpink";
c.strokeStyle="#000";
c.lineWidth=2;
c.moveTo(200, 50);
c.lineTo(50, 200);
c.lineTo(350, 200);
c.lineTo(200, 50);
c.fill();
c.stroke();
c.closePath();

See the Pen on CodePen.

You're not limited to straight lines - there are methods to draw arcs and curves of various kinds.

But even though you only have two primitive shapes, there are lots of different line styles, fill styles, and transformations you can perform. And you can import your own images too!

Why does canvas use two sets of width and height properties?

I said I'd come back to this after we'd done a little drawing, so here we go.

As you'll recall, we set a width and height on the canvas HTML element and in the CSS also. So what's the difference between the two?

Well, the width and height in the CSS change the actual size of the element on the page. So if you halve the numbers in the CSS, the canvas will be half as small on your screen:

#drawing {
width: 200px;
height: 150px;
margin: 10px;
border: 4px solid #000;
border-radius: 15px;
background-color: #fff;
}

See the Pen on CodePen.

However, note that the image we drew on the canvas has scaled to match this new size.

Now let's try the opposite - we'll put the CSS back to what it was, and then halve the width and height in the HTML. What do you think will happen here?

<canvas id="drawing" width="200" height="150"></canvas>

See the Pen on CodePen.

Ahh - we've zoomed in! The size of the canvas on the screen is 400px by 300px, but we're only showing the area we specified in the HTML - 200px by 150px - which is the top left quadrant of the image.

Experiment

The best way to learn canvas, is to simply play around with it! There's much more that you can do - try drawing a face, or a house. Learn how to detect mouse input, and have a shape change colour when you click on it. In in the right hands, it's a really powerful tool you can use to make beautiful games, elements, and interfaces.

Speaking of powerful tools for making beautiful sites, have you taken a look at fullPage.js yet? It's a JavaScript library that helps you build great-looking full page websites in a really easy way. You can use different transitions to move you from one page to the next, it works seamlessly with WordPress, Vue, and React, and it's super-efficient so it won't slow your site down.

Some big name brands are using fullPage.js, including Google, EA, and the BBC - so check it out and see if might work for you too!