Posts Tagged ‘ iPhone ’

iPhone Viewport Scaling

According to Mobile Statistics, Stats & Facts 2011, by 2014, mobile internet will take over desktop internet usage. And that’s not hard to believe taking into account the 1.08 bilion smart-phones on the market.
So, let’s suppose you own a smartphone. Then you have certainly navigated to a not mobile friendly webpage and you needed to zoom for making the text readable.

You probably know that zooming can be activated using the ‘viewport’ metadata.
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=2.0; user-scalable=1;" />

However, changing an iOS device orientation from portrait to landscape causes the page to scale larger than 1.0 and a part of the page (right) will be cropped. This effect will disappear if the user double-taps the screen, but lots of users don’t know about this trick.

The simplest solution would be to deactivate the zoom on your web-page by using the same value for ‘maximum-scale’ and ‘initial-scale’ or by setting ‘user-scalable’ to ‘0’ (on iOS you must use ‘no’ instead of ‘0’):
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=1;" />

But this won’t make the page easy to read on mobile devices. So, let’s try to find a fix for iOS.
Using media queries, you can write something like this:

@media screen and (orientation:landscape) and (device-width:320px) and (device-height: 480px) {
	body {
		width: 480px;
	}
}

which should force the browser to set the width to 480px (the resolution for iOS devices) on landscape. This rule should apply only for iPhone. If there are other devices with the same resolution, they won’t be affected because the 480px will be used anyway.

This rule might look OK, but there’s actually a bug on iOS which returns the same width (320px) for portrait and landscape and you can’t forced it to other values.
That’s pretty strange because Apple knows about this old bug, but they still sustain that’s the intended behavior. Why ? Probably they want to copy MS with their crazy IE exceptions. 😀

These being said, there’s only one solution left: to use JavaScript.
So, we can deactivate the zoom on iPhone when the page is loaded using the method explained above (same values for ‘initial-scale’ and ‘maximum-scale’) and activate it when the user starts making a gesture. Zoom will be activated by setting ‘initial-scale’ to 0.25 and ‘maximum-scale’ to 1.6 (default values from Apple’s Oficial document).
The original solution can be found here.

/**
 * Fix viewport when device orientation is changed and zoom is enabled
 */
function fixViewport(doc) {
	var event = 'gesturestart',
	    qsa = 'querySelectorAll',
	    scales = [1, 1], //initial scale width and height
	    meta = qsa in doc ? doc[qsa]('meta[name=viewport]') : [];

	function fix() {
		meta.content = 'width=device-width,minimum-scale=' + scales[0] + ',maximum-scale=' + scales[1];
		doc.removeEventListener(event, fix, true);
	}

	if ((meta = meta[meta.length - 1])) {
		fix();
		// enable zoom when gestures start
		scales = [.25, 1.6];
		doc.addEventListener(event, fix, true);
	}
};
function init() {
	//...
	if (navigator.userAgent.match(/iPhone|iPod|iPad/))
		fixViewport(document);
	//...
}

window.addEventListener("load", init, false);

The code searches in page metadata tags and modifies the ‘viewport’ metadata by setting the ‘initial-scale’ and ‘maximum-scale’ to 1.0 (deactivates zoom). When a ‘gestureStart’ event takes place, the zoom is reactivated.
In this way, the scaling bug is fixed and the user will still be able to zoom. Also, this fix won’t impact other mobile browsers which have correctly implemented scaling.