I previously wrote about the challenges of using media queries on Android given how much variation there is in the devices and the level of control end users have over the viewport.

That certainly doesn’t mean iOS devices are any less challenging! The real underlying problem is that the devices LIE about the screen size. They can lie because the pixels reported by the browser are not actual device pixels. There’s this little thing called a “device independent pixel” (or “dip”) and it has nothing to do with the “dots per inch” (or “dpi”) by which I mean the actual pixel count of the screen. The former is the “pixel density” and the latter is the “pixel resolution.”

Furthermore mobile devices tend to do a lot of scaling of web sites that desktop browsers do not. For example, if you look at a web site that has no coding in it aimed at mobile devices then iOS devices will zoom the page out and pretend the screen (regardless of how big it actually is, the resolution, or the pixel density) is 960 pixels wide. On an iPhone 3G it is actually 320 physical pixels in portrait and 480 in landscape, on an iPad it is 768 physical pixels wide in portrait and 1024 in landscape. But either way it will pretend that it is 960 pixels wide. However, if you add a viewport tag and tie the width to “device-width” you STILL aren’t going to get the actual physical pixel width. An iPhone will report 320 pixels wide in either orientation and an iPad will say 768 in either orientation. So they’re only truthful about device-width in portrait orientation.

So you think you’ll address that problem with media queries in your stylesheets? Nope. Even with media query conditions for widths of 1024 and 768 you’ll only ever see the one for 768 used because the device is lying about its width in landscape mode.   You can try to create two different media queries for 768 pixels by adding (orientation: landscape) to one, but the viewport will STILL only be 768 pixels wide (because that’s the fake “device-width” it says it is) so you’ll see your 1024 layout sure enough, but if you rotate from portrait to landscape it will be slightly zoomed in and the remaining 256 pixels will be off the right of the screen.

You could also try forgetting about the whole “device-width” thing since it’s a lie and just change your meta tag to:

<meta name=”viewport”  content=”initial-scale=1.0,minimum-scale=1.0″ />

Which will allow the page to use your media queries for 768 and 1024 but still causes the zoom-in problem when rotating from portrait to landscape.  You can zoom out, of course, to see the whole width but this is hardly a desirable user experience.

Ok, so how do you get it to show the different layout for 1024 pixels wide AND zoom out to show it all on changing orientation?  Well, you apparently have to sacrifice user functionality to do it. 🙁

<meta name=”viewport” content=”initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no” />

That will force it to zoom out, but it also means users can no longer pinch/spread zoom in/out.  The “user-scalable” part is kind of redundant since the maximum-scale is set to 1.0 anyway, but it drives home the point that user functionality is being sacrificed (and if I recall Android will ignore the rest if that isn’t there).

A better option is to accept that your 768 pixel layout will be used in landscape mode too and just design for that, ideally by using a fluid layout that can just adapt to whatever width the device is going to insist it has.