POSTS
CSS media selectors for mobile web - making it work on Android
I’m not a very good graphics artist/web designer. That doesn’t stop my trying though, as you’ll see through this site, and a plethora of others. I’m getting better all the time, but I’m still not up to a decent grade. This article is about one of those “getting better” moments, and I thought I’d share.
One of the things I like my sites to do is to behave differently on different sized screens, mobiles in particular. Often this is wrapped into the concept known as Responsive Web Design, but really its all about making your sites work on teeny tiny screens. So far, I’ve been doing this using CSS Media Selectors, which delivers different CSS styles to the browser depending on helpful information provided such as screen size. Although some people say that CSS media selectors are fools gold, I’m more inclined to think that they are sufficient for the majority of cases.
The basic principle is that when you create your CSS, you include some additional hints to the browser as to when it should be applied. Below is the usually accepted method, in which you place the following HTML tags in the <head>
of your document
<link rel="stylesheet" href="/css/style.css?v=2">
<link rel="stylesheet" media="only screen and (max-device-width: 480px)" href="/css/mobile.css" type="text/css" />
The idea is that you have your standard CSS first, which applies to the desktop version. The mobile version, which is only matched when the browser passes the media test, will override any settings that need to change the site to work properly on mobiles. This is the most basic media selector. You can also look at the orientation (landscape/portrait), the media it uses (printer, screen) and so on. I use this on this site, and in much greater depth on the jewellist’s portfolio site.
The problem is, they’re inconsistent, and they don’t always work. Many devices lie about these properties to try and get the right experience for users. In the above example, we’ve specified that the style will match on devices that have a maximum width of 480px. An iPhone4 has a maximum resolution of much wider than 480 pixels, thanks to its lovely retina display. In order to give users a consistent experience however, apple has made the iPhone lie about its resolution. Some browsers (notably Windows Phone 7) don’t even respect the media selector attribute. This means that developers that want to use these queries have to understand the quirks of the devices rather than have meaningful tests.
In an even more dangerous turn though, there’s been a bug in the Android implementation of WebKit (its built in browser) which has meant that it sometimes decided it wouldn’t apply the style sheet until you refreshed the browser. This has infuriated me for some time now, but I have found a workaround, thanks to this lovely post.
To make it work correctly on Android, you have to add an additional query parameter, which also matches any screens based upon their window width, in addition to the device width.
<link rel="stylesheet" href="/css/style.css?v=2">
<link media="handheld, only screen and (max-width: 480px), only screen and (max-device-width: 854px)" href="/css/mobile.css" type="text/css" rel="stylesheet" />
This is a hack to be sure, but it does work. It also shows another challenge to using this method. Notice how I’ve changed the max-device-width
parameter to 854px? Thats because we want it to work on landscape orientations too, ones that don’t lie about their resolution like the iPhone does. Some Android phones have lengths of 854px. This works great for current devices, but what about newer devices that have higher resolutions. The next generation of phones are likely to have 1280x720px screens, so these pixel based approaches will once again fall down (unless the phones lie).
All of this seems to push me in the direction of using User-Agent matching to deliver different content, rather than using CSS selectors. Most big sites seem to take this approach, having a www.blah.com site and a m.blah.com site. This also gives you the advantage of allowing users the option to switch over to the desktop version if they choose. It makes sense, but requires more server side logic, which kind of goes against my static website philosophy. I’ll need to look more into that…