The <canvas> element

Add a <canvas> to a webpage

To add a <canvas> to a webpage, place a <canvas> tag inside of the webpage’s <body> tag.

<canvas id="myCanvas" width="320" height="240"></canvas>

The id of the <canvas> is used to identify the <canvas> when sending it drawing commands. The width and the height of the <canvas> define the size of its bitmap image.

Store a reference to a <canvas> in a variable

var can = document.getElementById("myCanvas");

To get a reference to a <canvas> element, pass its id to the webpage’s getElementById() function. This reference can be stored in a variable and used to communicate with the <canvas> element later in a script.

Get the width and the height of a <canvas>

If we have a reference to the <canvas> element, we can get its width and height using JavaScript.

can.width;
can.height;

This way, we can avoid hard-coding width and height values in our script in case we want to change them later.

Set the width and the height of a <canvas>

We can also set the width and the height of a <canvas> element if we have a reference to it.

can.width = 200;
can.height = 200;

If we set either the width or the height of a <canvas>, the <canvas> will be reinitialized, which means any drawing on the <canvas> will be cleared and the context will be restored to its original state.

Save a <canvas> drawing as a PNG image

To save a <canvas> drawing in an image file, add both an <img> tag and a <canvas> tag to the webpage. Give both tags an id so that we can access them through JavaScript.

<img id="myImage" src="" width="320" height="240">
<canvas id="myCanvas" width="320" height="240"></canvas>

When adding an <img> tag to a webpage, the src attribute in the tag is normally the URL of the image file being displayed. However, since we are using the <img> tag to display the image drawn on the <canvas>—and not a image stored in a file—we leave the src empty.

Get references to both the <img> element and the <canvas> element.

var img = document.getElementById("myImage");
var can = document.getElementById("myCanvas");

Then, when the <canvas> drawing is done, tell the <canvas> to store the drawing in a data URL, and set the src of the <img> to the data URL.

var dataURL = can.toDataURL();
img.src = dataURL;

The toDataURL() function converts a <canvas> drawing into a PNG image that an <img> element can display. At this point, we should see two copies of the same drawing on the webpage: one image in the <img> element and one image on the <canvas> element. To actually save the PNG image onto our computer, all we need to do is right-click on the <img> element and choose “Save Image As…” in the pop-up menu.

Give a <canvas> a background color or border

Like any HTML element, a <canvas> element can be styled with CSS.

<canvas id="myCanvas" style="background-color:#eeeeee" width="320" height="240"></canvas>

By adding a style attribute to the <canvas> tag, we can give a <canvas> a background color. We will talk about how to define colors a little bit later, but #eeeeee is a light gray.

<canvas id="myCanvas" style="border:1px solid black" width="320" height="240"></canvas>

We can also put a 1-pixel-thick, solid, black border around the <canvas>. Drawing a border around the <canvas> increases the amount of space it occupies on the webpage. The <canvas> drawing is still 320 pixels wide, but the <canvas> plus its border is 322 pixels wide.

Sometimes it helps to see the edges of the <canvas> element while we are drawing on it.

Center a <canvas> on a webpage

We can use CSS to center a <canvas> element on a webpage if we wrap it in a <div> element. A <div> element is simply an empty container.

<div style="width:320px; margin:20px auto">
<canvas id="myCanvas" width="320" height="240"></canvas>
</div>

Use CSS to set the width of the <div> element to the same width as the <canvas> element. In CSS, we need to specify units when setting the width, so the width of the <div> element is 320px. Units aren’t used in the width attribute of a tag, so the width of the <canvas> element is 320.

The way we center a <div> element is by setting its left and right margins to auto, which tells the web browser to position the <div> element so that the left and right margins are the same size. In this case, we are setting the top and bottom margins to 20px and the left and right margins to auto. Sadly, setting the top and bottom margins to auto does not center a <div> element vertically.

I know that this mixing of HTML, JavaScript, and CSS can be confusing at times. They each have their own rules and it can be difficult to see how they fit together. My advice is to focus mainly on JavaScript for now. The HTML and CSS needed to draw on <canvas> is minimal at the beginning. You just need to know a little HTML to set up the webpage and a little CSS to define things like fonts and colors.

Add a hidden <canvas> to a webpage

Sometimes we want to use a second <canvas> to build parts of our drawing, but we do not want this second <canvas> to be displayed on the page.

<canvas id="mainCanvas" width="320" height="240"></canvas>
<canvas id="hiddenCanvas" style="display:none" width="320" height="240"></canvas>

Here we have our main <canvas> and a second hidden <canvas>. By setting its CSS display property to none, we do not just make the second <canvas> invisible, we set it so that it is not even occupying any space on the webpage.

Layer a second <canvas>

Normally, two HTML elements cannot be on top of one another. When a web browser assembles and renders a webpage, it lays out the page according to how much space each element occupies. If we add a new element to the top of the page, it pushes down all of the elements below it. This is known as page flow.

It is possible to remove an HTML element from page flow by setting its CSS position property to absolute. Then we can move it around without disturbing any of the other elements on the page.

<div style="width:320px; position:relative">
<canvas id="bottomCanvas" width="320" height="240"></canvas>
<canvas id="topCanvas" style="position:absolute; top:0px; left:0px" width="320" height="240"></canvas>
</div>

This is a fairly advanced technique and there are a number of pieces that have to work together to make it happen. We start by taking the top <canvas> out of page flow by setting its CSS position property to absolute. Once we do that, we can position it anywhere on the webpage by setting its CSS top and left properties. Any HTML elements that are positioned absolutely automatically float above the other HTML elements, so it will be on a layer above the bottom <canvas>.

However, setting the top and left properties of the top <canvas> will position it relative to the webpage, not relative to the bottom <canvas>. If we want to line up the two <canvas> elements precisely, we need to wrap both of them inside of a <div> element and set the CSS position property of the <div> element to relative. Now the top <canvas> will be positioned relative to the <div> element it’s inside, which is great because the top left corner of the <div> element and the top left corner of the bottom <canvas> have exactly the same position. Remember, the <div> element is simply a container for other elements.

Move a layered <canvas>

A careful reader will have noticed that I said we can position absolutely-positioned HTML elements by setting their CSS top and left properties. A playful reader will have asked, “Does it mean we can use JavaScript to move a layered <canvas> around a webpage?” Why… yes it does.

var topCan = document.getElementById("topCanvas");
topCan.style.top = "20px";
topCan.style.left = "110px";

If we have a reference to the top <canvas>, then we can get and set any of its CSS properties. For example, we could change the background-color of a <canvas> or make a <canvas> disappear by changing the value of its display property.

Attach an event handler to a <canvas>

A <canvas> element can listen for and react to events if it has an event handler attached to it. An event handler is a JavaScript function that is called to “handle” an event when the event occurs. Some common events that a <canvas> element may choose to handle include onclick, ondblclick, ondrag, onmouseover, and onkeypress. The browser generates these events automatically when the user does something.

There are three ways to attach an event handler to a <canvas> element. Each method has its pros and cons. One method is to attach the event handler in the <canvas> tag itself:

<canvas id="myCanvas" onclick="doSomething()" width="320" height="240"></canvas>

When the <canvas> element is clicked—either with the mouse or by a finger on a touchscreen—the doSomething() function will be called.

A second method is to assign the event handler to one of the <canvas> element’s event properties:

can.onclick = doSomething;

The third method is to use the <canvas> element’s addEventListener() function:

can.addEventListener("click", doSomething);

You should notice that, in these last two methods, we are assigning doSomething to the onclick property and passing doSomething to addEventListener()—not doSomething(). What is doSomething? It is a variable created automatically in JavaScript that contains a reference to the doSomething() function. We use the doSomething variable to pass the doSomething() function or assign it to a property.

I recommend using the third method unless you know what you are doing and have a good reason for choosing one of the other two methods.

If we attach doSomething() in the <canvas> tag using the first method, then we have no control over when the <canvas> element is clickable. It will be clickable as soon as the browser creates it and renders it on the screen. We can make sure that the doSomething() function is defined before the <canvas> element is clickable by defining doSomething() in a separate text file and loading that text file in the webpage’s <head>. Remember, the browser builds a webpage as it reads its text file from top to bottom. But if we call a drawSomething() function at the bottom of the webpage’s text file in order to draw on the <canvas>, and if we need drawSomething() to run before doSomething() runs, then we have a problem: the browser will create the <canvas> element and make it clickable before drawSomething() can run first.

We can avoid these timing issues by using one of the other two methods. Because both methods use JavaScript to attach the event handler in a script, we can simply wait to attach the event handler until everything is ready. If we attach an event handler with addEventListener(), we can also remove it at any time with removeEventListener():

can.removeEventListener("click", doSomething);

Sometimes we want the event handler to have a reference to the HTML element it’s attached to. For example, let’s say we want doSomething() to change the background color of a <canvas> element to light gray.

function doSomething() {
var can = document.getElementById("myCanvas");
can.style.backgroundColor = "#eeeeee";
}

Since property names in JavaScript cannot have dashes, the CSS background-color property is accessed through the JavaScript backgroundColor property. This works great. But what if we want to attach doSomething() to more than one <canvas> element?

All JavaScript functions have access to the this keyword, which contains a reference to the owner of the function. If we use one of the last two methods to attach doSomething() to the <canvas> elements, then the <canvas> element owns the function and we can modularize doSomething() by using the this keyword instead of hard-coding in a reference to a specific <canvas> element.

function doSomething() {
this.style.backgroundColor = "#eeeeee";
}

Unfortunately, if we use the first method to attach doSomething(), the owner of the function is the browser window and not the <canvas> element. Fortunately, there is an easy workaround. The this keyword refers to the browser window inside of the function, but this refers to the <canvas> inside of the <canvas> tag.

<canvas id="randomCanvas" onclick="doSomething(this)" width="320" height="240"></canvas>

So, we can pass doSomething() a reference to the <canvas> element it’s attached to by using a parameter.

function doSomething(someCanvas) {
someCanvas.style.backgroundColor = "#eeeeee";
}

When the user clicks on a clickable <canvas> element, the browser calls the attached event handler and creates an event object. This event object contains data about the event—such as the coordinates of the mouse click or the key pressed on the keyboard. It is automatically passed to the event handler as its first parameter if the event handler is attached using the addEventListener() method.

To access the event object within the doSomething() function, add an event object parameter to its function definition:

function doSomething(theEvent) {
var x = theEvent.pageX;
}

The doSomething() function gets the x-coordinate of the click, which is stored in the event object’s pageX property, and stores it in the the variable x.

If we are using addEventListener() and we want to pass multiple parameters, including the event object, to doSomething(), then call doSomething() from within an anonymous function:

can.addEventListener("click", function(theEvent) {
doSomething(theEvent, 10, "green");
});

Now when the <canvas> element is clicked, the event handler will call doSomething() and pass it the event object, the number 10, and the text string "green".

Another advantage of using addEventListener() is that we can attach multiple event handlers to the same HTML element for the same event, and we can selectively turn those event handlers on or off using addEventListener() and removeEventListener().

can.addEventListener("click", doSomething);
can.addEventListener("click", doASecondThing);

This <canvas> element will call both doSomething() and doASecondThing() when clicked. But if we use one of the first two methods, an event can only have one handler.

Examples

Learn more about using anonymous functions

Get event coordinates relative to a <canvas>

By attaching an event handler to a mouse or touch event, we can get the coordinates of the event if we attach the event handler using addEventListener().

can.addEventListener("mouseover", doSomething);
 
function doSomething(e) {
var x = e.pageX;
var y = e.pageY;
}

However, the event object’s pageX and pageY properties store the coordinates of the event relative to the webpage, not the <canvas> element that doSomething() is attached to. If we want to know the event coordinates relative to the <canvas> element, we also need to know the page coordinates of the <canvas> element.

function doSomething(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
}

The page coordinates of the <canvas> element can be accessed through its offsetLeft and offsetTop properties—and because we attached doSomething() to the <canvas> element using addEventListener(), we can access the <canvas> element using the this keyword.

Example

Scale a <canvas> for high resolution screens

For many years, one pixel on a webpage equaled one physical pixel in a computer screen. But with high resolution screens, that is no longer true. One pixel on a webpage can easily be 2 physical pixels wide and 2 physical pixels tall. To use those extra pixels and take advantage of those high resolution screens, we can use CSS to scale our drawings.

<canvas id="myCanvas" style="width:320px; height:240px" width="640" height="480"></canvas>

By setting the width attribute to 640 and the height attribute to 480 in the <canvas> tag, we create a <canvas> bitmap image that is 640 pixels by 480 pixels. But we scale the <canvas> image to 320 pixels by 240 pixels on the webpage by setting the CSS width and height properties.

Quadrupling the size of the bitmap of the <canvas> element will use much more memory and make drawing slower. I do not recommend scaling the <canvas> unless the higher resolution is necessary and you test for performance.

Learn more about finding the device pixel ratio

Example

Provide fallback content for a <canvas>

Some older browsers do not support the <canvas> element and some users block JavaScript from running. For those cases, we can provide fallback content. The fallback content will only be displayed if the <canvas> element cannot be drawn on.

<canvas id="myCanvas" width="320" height="240">
<img src="sadFace.jpg" width="320" height="240">
</canvas>

Fallback content is placed inside of the <canvas> tag. Here we are displaying a sad face JPEG image.

<canvas id="myCanvas" width="320" height="240">
<p>Your browser is unable to display this awesome drawing</p>
</canvas>

We can also leave a message to the user as fallback content. This way, they do not just get an empty white space on the page.