If you’ve ever tried to create a webapp or just optimize a responsive website layout to adjust for Android browsers you’ve probably torn out most of your hair by now. The good news is you’re not alone in your frustration. The bad news is that the default Android web browser is horribly broken and Google apparently has no interest in ever fixing it.
First of all, many many webapps and responsive websites were coded with fitting iPhone and iPad screens in mind. That makes sense, especially given the massive lead iPad has in the tablet game. If you’ve ever poked around in the component Java files for the default Android browser you might be amazed just how often you see the word “IPHONE” in there. So clearly Google was aware of this and made a half-assed effort to get the Android browser to play nice with sites optimized for iPhones.
Except, of course, it doesn’t.
Ok, before I go on I should explain “DIPS” in case you’re unfamiliar with them. The “dip” is a “Device Independent Pixel” which is sort of a virtual pixel, as opposed to an actual pixel on a screen. Up until somewhat recently nobody ever had to think about the “display density” because pixels were pixels – or you could say a “dip” equaled a pixel. On the original iPhone the screen was 320 pixels by 480 pixels. It’s display density was 1.0 so the screen was 320 dips x 480 dips. Things changed when Apple released their iPhone “Retina” display, which has a display density of 2.0. So now the screen was 640 x 960 actual pixels / 2.0 = 320 x 480 dips. Everything is visually the same size, it’s just at 2x the resolution. That 2x arrangement was very convenient for anyone updating the visual assets of their apps or websites to take advantage of the higher resolution screen – and by using image files 2x larger your stuff no longer looked blurry on a “Retina” screen.
Android uses “dips” too. But the fragmentation of having many manufacturers, screen sizes, screen ratios, etc., means there really is no “default” display density you can count on. As if that wasn’t bad enough the Android default Browser (unimaginatively named “Browser”) has a “Default Zoom” setting, which I’d wager most people never change from the default setting of “Medium.” But the other possibilities are “Close” and “Far.” On top of that there is another setting to “Use Wide Viewport” an option to change the linear rendering algorithm, a “Fit Page” option, and yet another that attempt to override delivery of the “mobile” version of a website and fetch the “desktop” version instead.
Seriously, you can’t know what size anything will render on an Android browser. Ever.
Google could’ve made this easy on us. They could’ve set up the default Browser so it would automatically zoom responsive websites and webapps with a mobile intent to a virtual 320 pixels wide in portrait and either 480 pixels or 568 pixels (for widescreen) in landscape orientation. If they’d done that ALL the content out there already coded to target iPhone would have automatically worked perfectly on Android too. But, of course they didn’t and it doesn’t.
Now, you may at this point be saying that nobody should be coding things FOR any device in the first place. Aren’t we supposed to be doing “device independent” design? Liquid layouts? Well, yeah we should. If you coded everything as a liquid layout you’d never have to worry about this at all. But of course, in the real world, clients want what they want and too often a seriously flexible liquid layout is also too spartan or simple or they just don’t like it – they want things they’ve seen in apps and it’s usually not worthwhile trying to explain why aping a “native app” appearance is setting up end users for a disappointing “webapp” experience. And so a balance needs to be struck between “liquidity” and the constraints of screen size and orientation.
On top of the annoyances that can be caused by Android’s many browser settings, since Android 4 came out the default Browser has a bug in the “Default Zoom” that means it pretty much ignores changes to the setting. It will keep using whatever the preprogrammed default size is in the app’s database (and you can’t count on it always being medium. It appears device manufacturers – especially if they use a custom skin on Android – might change this, as it was defaulting to “Close” zoom on my brother’s LG phone). The default Browser also has a long-standing problem understanding meta viewport settings that attempt to restrict user scaling. Basically it’s completely broken, it’s been that way for multiple updates, Google doesn’t seem interested in ever fixing it.
Some of this stuff is also broken in Google’s *other* browser for Android – “Chrome.” In just about every way Chrome is a nicer browser for Android than the default one, but it’s also nowhere near as customizable. It doesn’t even HAVE that setting to change the default zoom. It also has an option to override the meta user scaling setting.
What this tells me is that Google isn’t all that interested in investing any more development time in the default Browser. And the Chrome browser still has a ways to go and only recently emerged from “beta.” It would be nice, especially if Google is truly intent on taking away the end user’s ability to change these settings, that they settle on some “standard” rendered width for phones and tablets in both portrait and landscape orientation. It obviously doesn’t have to be the same as iPhone and iPad, but it would make my life a helluva lot easier if I only had to target, say, FOUR virtual widths to cover the majority of mobile devices.
The way I tend to think about my media queries in my stylesheets, in order to optimize for various mobile devices is something like this:
Fallback, most liquid layout for old browsers and defaults for all browsers outside of the media queries.
@media screen and (min-width: 1024px) and (max-width: 1366px) – targets most Windows laptops and tablets in landscape, also iPad in landscape.
@media screen and (min-width: 768px) and (max-width: 1023px) – targets iPad in portrait and low-res desktop screens.
@media screen and (min-width: 768px) and (max-width: 1023px) and (max-height: 480px) – targets Android phones and tablets in landscape mode with browser zoom set at “medium.” Hopefully. No guarantees.
@media screen and (min-width: 480px) and (max-width: 767px) – targets iPhone 4 and 5 in landscape, plus some Android phones.
@media screen and (min-width: 480px) and (max-width: 767px) and (min-height: 600px) – targets Android phones in portrait orientation with browser zoom set at “medium” – should nab both 4:3 and widescreen ratios. Again, no guarantees. But it prevents Android users form seeing the iPhone landscape view in portrait orientation.
@media screen and (max-width: 479px) – this targets iPhone 3 & 4 in Safari Mobile in portrait orientation, it also grabs Android phones in portrait with the browser set at “Close” zoom level. This is the general phone in portrait fallback view.
@media screen and (max-width: 479px) and (min-height: 460px) – targets iPhone 3 & 4 in portrait “App View” (bookmarked to home screen) and iPhone 5 viewed in Safari Mobile.
@media screen and (max-width: 479px) and (min-height: 532px) – targets iPhone 5 in “App View” and Android phones with “widescreen” displays in portrait orientation with the browser zoom level set at “Close” view.
Below these I then repeat any of them I need to with the extra query for higher pixel density to target “Retina” displays with optimized images.
This flow seems to work for a lot of stuff, but I always end up making minor modifications to it. For example, sometimes I don’t dial in a “min-width” if I actually intend for the style to cascade over the smaller screen sizes. And that is how my CSS typically ends up – it’s starts “big and wide” and goes “small and tall.” Your mileage may very, but hopefully this will ease some of your frustration. And I’d strongly recommend always checking your project in the iOS Simulator, some of the predefined device configurations in Android Emulator, and as many ACTUAL devices as you can get your hands on.