Fitting screen in HTML5 games

Past entries

Though I haven't released anything for some time, I have been working on several new games during the past months. One thing that I've been struggling with is to make the games adapt to the screen size. I used to make single-size games adapted for the iPhone, thinking that it would be enough, but I've come to realize that I can't rely on that solution anymore.

The problem with resizing the game is that it can also affect the gameplay. I could totally make the canvas fit the screen, but the experience would depend on the device, and I don't want that. So the idea is to choose a size, stick to it, and then adapt the canvas to the screen, so it's only a matter of display.

Here is the code I use to make the canvas fit the screen size. It keeps the initial ratio and calculates the best size for the specified element. It is directly taken from my JavaScript toolbox.

	// ...
	/**
	 * Makes the specified element fit screen size.
	 * Once the window is resized, you will need to call this function
	 * again.
	 */
	fitScreen : function(element,ratio){
		var clientRatio = window.innerWidth / window.innerHeight;
		
		var width, height;
		if(clientRatio <= ratio){
			width = window.innerWidth;
			height = width / ratio;
		}else{
			height = window.innerHeight;
			width = height * ratio;
		}
		
		element = DOM.get(element);
		element.style.width = width + 'px';
		element.style.height = height + 'px';
		
		// Returning the element's size
		return {
			width : width,
			height : height
		};
	},
	// ...

Here is a layout that may help you understand the algorithm:

This is the method I've been using for a long time now, but there is still the question of how to implement it. Here are some of the solutions:

  • directly set the canvas size, and then scale the context (i.e ctx.scale(x)) to use the whole screen. This method works pretty well, but it requires some additional JavaScript, which I don't really like. Also, I'm not too sure about the performance. The problem with this method is that if you use any DOM elements, you will also have to scale them. This is the method I used for Ski!. You can easily see that the menus are too small compared to the actual game.
  • using CSS transforms to scale the whole game (canvas and DOM elements). This method has the advantage of resizing everything. That means that if you have DOM elements in your game, you won't have to think about resizing them as well. Though, I'm not sure that CSS transforms are really fast, and I have experienced some issues with old versions of Android when using forms. I used this method in Space Dodger, but I removed it because the game felt even slower. I'm not sure I would recommend this method.
  • resizing the canvas container, and using a 100% width on the canvas with CSS. This is the method I'm using for my new games. I like it because it does not require any additional JavaScript, and the CSS is really simple, and probably faster. Still, DOM elements won't be scaled, unless you apply CSS transforms on them.

The third method is the one I'm using now, because it is the easiest one to implement, but it still raises the problem of the DOM. The solution could be to decide not to use any HTML, but then you would give up some wonderful things: DOM provides forms, links, clickable areas, easily customizable elements with CSS, and is faster. If you decide to only use canvas, and therefore to display everything with JavaScript, you will have to implement all these little things you've given up. Even implementing a clickable area could be annoying. But the advantage is that you don't have to care about resizing your menus, which can be relieving.

For this reason, I'd suggest to use canvas only if you're only going to use simple effects and interactions, and DOM if you're willing to have something a bit more complex, like a text box, for instance.

To resize my DOM menus, I've chosen to use a simple solution. I use a fixed-size menu, and then I make sure it is always at the center of the screen, using simple CSS. It has to be small enough, because I'm not resizing it, so I just choose the iPhone screen size (320*460, or 480*300).

Also, there is the problem of bigger screens: should I make the game fit the screen size, and make it a bit more blurry and slower? On mobile devices, of course it's better to use the entire screen, but what about computers? I feel really uncomfortable when playing a fullscreen HTML5 game on my browser, because it is slower, and because of the quality loss. That's why I've decided not to resize my games for computers by simply detecting whether the user has a touch screen or not. Though, this is only my personal choice and people might prefer to play fullscreen, even on big monitors.

To finish, resizing the screen also has an impact on user interaction. When your game has a fixed size, you can easily determine where the user clicks, but when your game fits the screen size, you have to add some calculations to know the exact position of the click, on the canvas. Though this is only a matter of one line of code, I've always found this aspect particularly annoying when making games with complex user interactions.

I hope this post was useful, and though you might already have found your own solution, it might be a good idea to think about it and consider other solutions.

< Introducing Space Fight
Canvas star effect >