Using Media Queries in the Real World

Recently I’ve been working on the new website for my employers, Poke London, which launched last week. One of the things of which I’m proudest is the use of media queries to create a site which is sympathetic to small-screen devices. I learned a lot from developing with media queries, not least of which was the limit of what’s possible with them, so I thought it would be useful to present some of the key lessons learned in this post.

By the way, throughout this post I will refer to the ‘mobile version/site/theme’; I’m aware that’s a loaded term as the site won’t work on many mobile devices, but I’m using it purely as a convenient shorthand for ‘handheld device that supports media queries’.

Basic first, enhanced second

One of the biggest requirements of making a mobile site is to keep it as light as possible; don’t load any page assets that you don’t need. On pokelondon.com we use large background images, which would slow down the loading time noticeably on mobile devices which aren’t wifi connected, as well as eating up data allowances.

Many sites which pioneered the use of media queries have built a desktop version first, and then used media queries to hide assets from mobile browsers. This is not optimal, because using display:none means only that the asset isn’t shown — but it is still loaded. The only way to not load an asset is to not include it in your stylesheet. The way I achieved this is by making the mobile stylesheet the default, and adding in the heavier page assets for the desktop theme using a media query:

<link href="style.css" media="screen" rel="stylesheet">
<link href="desktop.css" media="screen and (min-device-width: 768px)" rel="stylesheet">

So the default stylesheet is the one you see on the mobile device, and devices with larger viewports get the extras. The reason I chose 768px for the minimum device width was mainly to accommodate the iPad and any similar tablets that appear in future. We decided that iPad users should get the full site experience, and as the iPad’s shorter screen side has a width of 768px, that’s the figure we chose. Any device with a lower resolution gets the mobile version.

Very old browsers that don’t support media queries (support table) will also see the mobile version of the site; that’s not a problem, as they still get access to all of the content. The mobile site is in no way inferior to the desktop site; although it is missing some of the functionality (notably the multiple views for the portfolio) it has all of the same content, but is better suited to a smaller screen.

Remember Internet Explorer

Modern browsers have supported media queries for some time now, but IE9 is the first version of Internet Explorer to do so. To accommodate that you need to add a conditional comment to load the desktop stylesheet for IE8 and below:

<!--[if lt IE 9]>
<link href="desktop.css" media="screen" rel="stylesheet">
<![endif]-->

The image and object problem

I’ve already mentioned how to not load background assets, but unfortunately there’s no easy way to not load elements in the markup, such as img or object, which could be quite heavy. This is something pokelondon.com still suffers from; although the images in the blog posts on the home page are not shown, they’re still downloaded in the background.

Looking at ways around this will be the next step of the project. One approach we’re considering is replacing images on the server side with an empty element, like:

<div class="img" data-height="100" data-src="image.png" data-width="100" />

And then using JavaScript to rebuild them for the desktop version, perhaps like:

$('.img').each(function(){
    var imgHeight = $(this).data('height');
    var imgSrc = $(this).data('src');
    var imgWidth = $(this).data('width');
    var thisImg = $('<img height="'+imgHeight+'" src="'+imgSrc+'" width="'+imgWidth+'">');
    $(this).replaceWith(thisImg);
});

I haven’t actually tested this code, it’s just off the top of my head; but that’s the basic principle I’d be applying. The advantage of this is that the mobile version doesn’t have to load extra images; the only real downside is that users with JS disabled don’t see the images either. However, as the images on our site are used for decoration rather than illustration, I think that’s an acceptable loss.

The second part of this issue is where we do want to show images, such as on the individual blog posts and portfolio projects, but we’ve had to resize large images in the browser rather than serve up mobile-optimised ones. A way around this could be to use a service like tinySrc to serve resized images; initial tests have thrown up a few issues which would mean it’s probably not ideal, but we really haven’t looked into this too deeply yet.

JavaScript media queries

As well as providing relevant CSS rules to the desktop and mobile themes, I also needed to provide relevant JavaScript functions. To do this I used the JS equivalent of the device-width media feature, which is screen.width, and made a ternary operator which works on the same width value as min-device-width:

var screenWidth = (screen.width < 768) ? true : false;

So if I wanted to use a script only on the mobile theme (as I did to move the navigation from the top of the page to the bottom, for example) I would use this:

if(!screenWidth) { ... }

Media queries can’t be an afterthought

Probably the most important point I learned was that if you’re planning to use media queries, that decision must be made at the very start of the project, because it affects not only the way you write your CSS, but also your markup. In order to make pages that adapt easily to different device viewports, you must make decisions about how to mark up your content in a way that allows for that adaptation.

Throughout the project I tested on both desktop and mobile concurrently, making sure that the way I’d coded for one didn’t impact badly on the other. If I’d built for desktop first and mobile second (or vice versa) I would have had to make many changes to existing code, which would have had a very negative impact on my time.

One thing I didn’t get right was the print stylesheet; it should have been considered from the beginning and developed at the same time as the other stylesheets, which meant I could have factored in the common rules when deciding in which stylesheet to place them. As this didn’t happen, I ended up duplicating a lot of rules from the screen stylesheets.