Dynamically scaling the HTML5 canvas.

One of the problems I've run into while building an html5 canvas game is scaling the size of the game based upon the browser's viewport size. Luckily the canvas element is treated just like an image (img) element when it comes to resizing.

To start off we are going to draw a simple rectangle on the canvas.

    var container = document.getElementById('dynamic-canvas-size-container1');
    var canvas = document.createElement('canvas');
    canvas.width = 150;
    canvas.height = 150;

    var context = canvas.getContext('2d');

    context.fillStyle = 'blue';
    context.fillRect(0, 0, 150, 150);

    context.translate(canvas.width / 3, canvas.height / 3);
    context.fillStyle = 'red';
    context.fillRect(0, 0, 50, 50);

When scaling an image we would usually like to keep it's aspect ratio. If you don't you end up with warped images that don't look very good. For instance our width/height ratio of the canvas above is 1:1 so it makes a perfect square. To scale an image/canvas well we use the below methods:

    var getResizeRatio = function(startWidth, startHeight, maxWidth, maxHeight){
        var ratioX = maxWidth / startWidth;
        var ratioY = maxHeight / startHeight;

        return ratioX <= ratioY ? ratioX : ratioY;

    var getResizeDimensions = function(startWidth, startHeight, maxWidth, maxHeight){
        var ratio = getResizeRatio(startWidth, startHeight, maxWidth, maxHeight);

        return { width: Math.round(startWidth * ratio), height: Math.round(startHeight * ratio) };

Once we have the above methods we can easily resize our canvas while keeping it's aspect ratio. Just use the code like so:

    var dim = getResizeDimensions(canvas.width, canvas.height, 450, 1000);
    canvas.style.width = dim.width + 'px';
    canvas.style.height = dim.height + 'px';

Notice that I attempted to make the height a lot bigger but the getResizeDimensions method kept the aspect ratio, so we just end up with a larger rectangle (as we should). When writing HTML5 canvas games you'll have a little bit of a problem dealing with user input and resizing. Luckily I've written a framework to handle all of those issues. I'll post about it in a bit.