Fixing the iOS orientation / viewport zoom bug

By Mike Swartz June 21, 2011

Jeff discovered an iPad and iPhone related issue with scale while working on and testing an independent project with a responsive layout – and found a solution on Stack Overflow which could use some publicity (and possibly some further eyes on the code).

Jeremy Keith’s post on Orientation and Scale summed up the issue as well as the solution used here. Jeff’s development project deals with a layout that is 3 columns on iPad landscape, and 2 columns on iPad portrait. 

Using just the standard responsive scale meta tag, the site loaded in landscape correctly:

When turned to portrait, the site adjusted appropriately – great:

But when turned back to landscape – ehh:

By default the iPad changes the scale of document when going from portrait to landscape.

Here’s the fix:
Retaining the current responsive meta tag code is best, as it continues to give a fallback user the ability to scale the page using the pinch gesture (whereas locking the user into a scale of 1 off the bat automatically denies that feature).

<meta name=”viewport” content=”width=device-width, initial-scale=1”>

Rather, we place that responsibility with the Javascript. Here’s the Javascript fix:

if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) {
  var viewportmeta = document.querySelector('meta[name="viewport"]');
  if (viewportmeta) {
    viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0';
    document.body.addEventListener('gesturestart', function() {
      viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
    }, false);

To sum up the Javascript, it begins by disabling page scaling, so that if the device orientation is changed, there is no change in page scale. But then, if the user requests to zoom in on the page by making a pinch gesture, page scale is triggered back on (in which case, we lose our control over scale when changing between orientations).

And like magic, Jeff’s layout now retains its appropriate scale when changed between orientations. The solution isn’t 100% flawless – with some delay when scale is triggered back on by the user’s pinch. Again, thanks go out to the Adactio post, where Jeremy Keith goes over the solution and changes made along the way in detail.