Resizing HTML5 Canvas and Scaling Sprites
I'm working on a game using HTML5/JavaScript and I ran into a problem: Mysprites were created as 8x8px and that would be way too small to view on high resolution displays. Not only that, I wanted the size of the canvas to adapt to whatever display it was being viewed on without distorting my sprites, and I didn't want the canvas to take up the entire window.

I wrote a sample to show how to go about scaling the canvas to your browser window up to a max height/width, which you can view oncodepen or clone fromgithub. I'll explain it below:
First, create a<canvas>
inside a container<div>
.
<divid="game"><canvasid="canvas"></canvas></div>
Next, you'll need to add some styling to get the canvas to stay in the center. Remove margin from<body>
and<html>
and make it take up 100% of the window. Then add flexbox to your container<div>
and give it a height and width of 100% as well.
html,body{margin:0;height:100%;width:100%;}#game{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;width:100%;}
Now get a reference to your<canvas>
and canvas context, and set the initial width and height.SIZE
refers to the sprite's size, which is 8 pixels wide by 8 pixels tall.map
refers to my 2D array. How to create the map is out of the scope of this post, but you can check out the source code to see how it's done.
constctx=document.getElementById('canvas').getContext('2d');// size of each 'tile'constSIZE=8;// native width and height (does not change)constnHeight=SIZE*map.length;constnWidth=SIZE*map[0].length;functionrender(){tiles.forEach(tile=>{ctx.drawImage(tilesheet,tile.srcX,tile.srcY,SIZE,SIZE,tile.x,tile.y,SIZE,SIZE)})}window.addEventListener('load',()=>{ctx.canvas.width=nWidth;ctx.canvas.height=nHeight;buildMap();render();})
At this point your canvas is going to be very tiny since it's using your native game resolution (which, in this case is 56x40). Your native game resolution does not change. It's used for your game's logic, such as character movement, collision, etc.

In order to scale your canvas you'll want to keep track of a separate width and height for your canvas resolution. If you don't want your canvas to extend to the width/height of the window you can add your own max width/height and/or add a percentage of the window that you want to be taken up. You can play around with this; you might not need or want both or either of these settings.
// I just picked 20 at random here.// In this instance maxWidth = 56 * 20 = 1,120 and maxHeight = 40 * 20 = 800constmaxMultiplier=20;constmaxWidth=nWidth*maxMultiplier;constmaxHeight=nHeight*maxMultiplier;// % of browser window to be taken up by the canvas// this can just be set to 1 if you want max height or widthconstwindowPercentage=0.9;// the canvas' displayed width/height// this is what changes when the window is resized// initialized to the native resolutionletcHeight=nHeight;letcWidth=nWidth;
Now when you load, you want to set your canvas dimensions to the variables you're using for your canvas resolution as opposed to your native resolution. You also want to set up an event listener to watch forresize
, and in there you want to handle your canvas resizing as well as re-render.
window.addEventListener('load',()=>{// initialize native height/widthctx.canvas.width=cWidth;ctx.canvas.height=cHeight;buildMap();resize();render();})window.addEventListener('resize',()=>{resize();render();})functionresize(){cWidth=window.innerWidth;cHeight=window.innerHeight;// ratio of the native game size width to heightconstnativeRatio=nWidth/nHeight;constbrowserWindowRatio=cWidth/cHeight;// browser window is too wideif(browserWindowRatio>nativeRatio){cHeight=Math.floor(cHeight*windowPercentage);// optionalif(cHeight>maxWidth)cHeight=maxHeight;// optionalcWidth=Math.floor(cHeight*nativeRatio);}else{// browser window is too highcWidth=Math.floor(cWidth*windowPercentage);// optionalif(cWidth>maxWidth)cWidth=maxWidth;// optionalcHeight=Math.floor(cWidth/nativeRatio);}// set the canvas style width and height to the new width and heightctx.canvas.style.width=`${cWidth}px`;ctx.canvas.style.height=`${cHeight}px`;}
Inresize()
, you first setcWidth
andcHeight
(the canvas resolution variables) to the window'sinnerWidth
andinnerHeight
. Then you need to get the ratio of width to height for both your native resolution and your browser window. If the ratio of the window'sinnerWidth
/innerHeight
(cWidth/cHeight
) is greater than the native resolution ratio (nWidth/nHeight
) then the browser is too wide and you need to recalculate the width so it meets the correct ratio. Otherwise, the browser window is too high and you need to recalculate the height.
If you want to set a max window percentage you can set the new canvas width/height by first multiplying their values bymaxPercentage
. If you want to use a maxWidth/maxHeight you can check if thecWidth
andcHeight
values are greater, and if so, set them to their max. After, or instead of, all of that, you can set the final new width or height values (depending on which condition you hit). The newcWidth
is calculated bymultiplyingcHeight
bynativeRatio
and the newcHeight
is calculated bydividingcWidth
bynativeRatio
.
Next, set the canvas'style property's width and height to the newcWidth
andcHeight
. "Canvas.width and canvas.height set the size of the canvas. canvas.style.width and canvas.style.height set the resolution."
Finally, addimage-rendering: pixelated
to yourcanvas
styles so that your pixel art isn't blurry.
canvas{image-rendering:pixelated;}

That should be it. I know I assumed a lot of prior knowledge with canvas and setting up sprites and the game map, so if you're struggling leave a comment and maybe I, or another reader, can help!
Here are some links if you're interested in reading or watching more about this topic.
- 28- Making HTML5 Game: Resizing Game Part 2. Javascript Tutorial Guide
- Advanced Game Design with HTML5 and JavaScript by Rex van der Spuy
- Building JavaScript Games for Phones, Tablets, and Desktop by Arjan Egges
- Scaling a Javascript Canvas Game Properly
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse