Using Media Queries in the Real World

Warning This article was written over six months ago, and may contain outdated information.

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.

59 comments on
“Using Media Queries in the Real World”

  1. Your stupid site doesn’t work when resized down in a desktop browser. I don’t know how your trying to make it “sympathetic to small-screen devices” but it isn’t very robust or responsive. I wouldn’t be so proud if I were you.

    Also the site as a whole looks absolutely horrible in all latest version of Chromium. Especially the top navigation.

  2. Definitely a logical step for media queries.

    Still the fact does remain that there is no way of effectively controlling markup. I can’t imagine it’s too hard to come up with a php based solution.

  3. The problem with doing anything on the server side is that it becomes effectively about browser/platform sniffing rather than device independent. We did explore that option, but the disadvantages outweighed the advantages — on this project, at least.

  4. I’m really fond of this sort of “mobile first” approach. I’ve seen a few other sites take a similar approach, most notably Yiibu and Jeremy Keith’s Tweaking Huffduffer.

    I attempted something similar on my own site last month.

    What exciting times to be in web design!

  5. […] Using Media Queries in the Real World » Broken Links […]

  6. […] own trials and tribulations with responsive design concepts. That means we should expect lots of blog posts and tweets regarding frustrations and accomplishments. So keep reading and keep creating. I, for […]

  7. Quick question for you Peter — how does that minimum device width play with the iPhone 4/Nexus One and S in landscape mode? Does it still achieve the desired effect?

  8. @Loz Despite the larger resolutions (Galaxy S is 480x800, iPhone 4 is 640x960), both still display the mobile site in landscape mode. I haven’t really looked into why this is, but I’m presuming that device-width is calculated from the shorter side.

  9. […] Using Media Queries in the Real World […]

  10. This device width stays the same when you switch to landscape mode. It is not updated to reflect the wider screen you now have available.” — PPK refers to iOS in his article, but it might very well be true for Android phones (can’t check, I don’t own either one of them). If I understand this correctly, device-width i.e. on an iPhone 3 is always 320px, even in landscape mode where the actual width is 480px.

    Here’s another question for you: If you split CSS files and include them the way you proposed above, are they not even loaded on a smaller device or are they just not being executed? Because if they’re just not being executed, it might be wiser to keep them in one CSS file (using @media there) to save some requests. (Yes, there might be cases in which it would still be a good idea to split them because a single CSS file could get huge.)

  11. @Matthias — Yes, this is also true of Android phones — or my phone, at least, and I’d imagine it’s consistent.

    My understanding of the issue is that you split the CSS files then they are not loaded at all; I initially considered putting all of the rules in the same file, but I read somewhere — and I can’t remember where — that if a CSS file is loaded, all of its assets are also loaded, regardless of whether they’re used or not. That said, my usual preference is to split files anyway.

  12. Great post, one small suggestion is that in your JS you could do this..

    var screenWidth = (screen.width < 768);

    Instead of

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

  13. I do not agree Toby,

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

    is more clearly.

    Also as Lewis mentioned I think server side script is the best solution to fix the mark-up problem. There are some libraries out there that are quite accurate on these checks. I guess the chance these get it wrong is smaller then someone not having javascript enabled.

    Still I like your approach of putting the mobile version first and add stuff as the device gets “stronger”.

    Cheers

  14. you could put the images as background images. They are loadable via CSS.
    Holger

  15. @Holger: That’s an interesting idea; the problem is that the site is managed by CMS and the editors can place images anywhere they want, but I could pre-process the information and replace an img element with a div with a background image, and use CSS to hide that… good approach, I’ll think it over some more!

  16. I love the idea of presenting mobile stylesheets first, and I’ve been using it in many of my web sites and apps a lot the past couple months.

    Unfortunately, from my tests, both the stylesheets above, basic.css, and desktop.css, will be downloaded on mobile browsers. I’ve tested iOS, WebOS, Android, FF Mobile and Opera and they all download both stylesheets. Desktop browsers also download both stylesheets if you set min-device-width to something high like 6000 px.

    It works properly because the mobile devices don’t apply the desktop styles, but that weight is still downloaded to the devices.

    The only solution I have is to use some JS and detect the screen width and load the desktop.css dynamically.

  17. Hi Peter,

    I had a few thoughts whilst reading your article:

    - You could use a javascript to dynamically load in different script sets depending on whether it was the mobile or desktop version. If the desktop version used jQuery but the mobile version did not this could save a lot of bandwidth.

    - You could load mobile versions of the images and then use javascript to turn them into the desktop versions.

    - It would be interesting to do resource loading based upon bandwidth rather than screen width (particularly given mobile tethering, iPhone hotspots, and the like.

    I’ve put some example code and longer explanations here: http://smallhadroncollider.com/three-ideas/

    What do you think?

  18. […] reading the post “Using Media Queries in the Real World” by Peter Gasston, I switched around my media query to target desktop sizes rather than mobile sizes. It makes more […]

  19. Thank you for this clean and clear explanation. I have been experimenting with using media queries to react to screen size than picking up that alteration in CSS via jQuery and changing the DOM or running an ajax request back to the server to alter the page. I posted an example updated with your helpful information in this post: Mobile Detection with CSS and jQuery: Part 2.

    BTW, I cannot seem to subscribe to your RSS feed…it is giving me an error.

  20. @Ryan: First of all, I don’t know why you have to be so aggressive; your criticism would be more acceptable if you could use some basic social grace. Anyway, it doesn’t change when you resize the browser because I’ve used the device-width media feature, not the width feature; by your not realising that, I know you haven’t read the article properly. As for the header comments, what do you mean by that? That’s a very non-specific criticism, so how should I address it?

    @Thomas J Bradley: The tests we ran indicated that the stylesheets were being ignored; I’ll have to double check our results. Certainly the page load speed increased by quite a lot.

    @Mark Wales: Great article, we’ll be looking in to your proposals as part of a second round of changes.

    @Jen: Thank you. I’ll read your article over the weekend when I have more time — I’ll also look into the RSS problem.

  21. @Mark Wales — I read through your article again. Points 1 & 2 are very good; it’s true that on PokeLondon.com there are still more optimisations to be made, and we don’t need most of jQuery. This might be a good place to use yepnope.js. I think your third point is a good idea, but not sure if it works in practice. Would be great if mobile browsers had an API to access to find out if Wifi were connected or not.

    @Jen — I read your article too. Interesting approach, which may be useful to us in future revisions. Also, the RSS feed should hopefully be sorted out now.

  22. Great concept and I think the methods that Thomas J. Bradley and Mark Wales reference are great. However, one minor(?) issue I found with using JavaScript to inject a ‘deskop’ version CSS file. When testing on a fairly slow server, I found there was a noticeable FOUC from before and after the ‘deskop’ CSS was applied. Anyone else notice this?

    FYI — the ‘desktop’ stylesheet is getting applied to the DOM before the page loads, so it’s not a case of me waiting for a DOM ready event or window onload event to fire.

  23. I really like the approach of creating a base for smaller screen sizes first, too, as it means that old mobiles don’t have to be capable of reading media queries to have styling that’s not problematic for them.

    Any more to add on whether or not “desktop.css” in your example is downloaded (along with any background images) by devices with device-widths lower than 768px?

  24. Also, I’d be interested to hear what your issues with tinySrc were — looks very interesting. Thanks.

  25. @David Oliver — Haven’t had time to run more tests yet, but will post the results here when I do. I’m pretty confident that even if a stylesheet gets loaded, the assets within it don’t.

    Also, the first image we tested with tinySrc didn’t scale well as it was too tall (it was, admittedly, a *very* tall image). Also, we have concerns about what happens if their server goes down; they have no support agreements in place. For personal use I’m sure it’s very good.

  26. Your image replacement via JavaScript technique will prevent browsers from performing a look-ahead, speculative download of the resource, impacting load time a fair bit.

  27. @Nicholas Shanks — Thanks Nicholas, we’ve yet to implement it (we’re looking at a server-side solution right now) but we’ll bear that in mind.

  28. @David Oliver — Very rough preliminary tests show that when using media queries, all CSS files get loaded but the contents of any which don’t match the requirements of the given media features are ignored. So no background loading.

  29. Thanks Peter. I want to test this myself, too, but it’s good to hear your preliminary results for comparison.

  30. I suppose it also depends on how each browser does it. Although a browser we test might not load background images, perhaps a different browser on a mobile will.

  31. Great article, Peter. Thanks! I’ve been doing a lot of work and testing with MQ lately as well (desperately need to blog it). I can weigh in on a couple issues here. My husband blogged our findings about what CSS documents, and resources inside them, are downloaded in Dec on his blog Assorted Garbage.

    Also, I don’t know if you’ve seen it before, but there’s some very cool experimentation going on by Scott Jehl and Filament Group on responsive (mobile first) images. It may help solve your image challenge. I’m very interested in this approach since it’s more agile and allows you to keep things accessible (with alt text, etc). I haven’t been able to try it on a project yet, however. (And there’s not a similar project with objects, AFAIK.)

    (Also, for those that are interested, there’s a tiny script—Responsive.js—by the same folks. It will detect browsers that don’t support MQ and then add the support.

    My biggest challenge with this new development paradigm is, like you say, building it this way from the start. I receive comps (I do front-end development) that are typically created for desktop first — with deadlines. So sadly, much of the time I end up doing the desktop first, and then trying to switch things around in the end — which can be confusing. It makes me wish that either A) I was a designer myself or B) We could train more designers in this method more quickly.

    Thanks for helping to get the word out. :)

  32. @Stephanie: thanks for the links — interesting. The more I read and think about this topic, the more I find myself preferring a server-side approach of first determining if the accessing device is a mobile and then serving the appropriate stylesheets based on that rather than relying on media queries to server/not server CSS and CSS images. Although your husband’s tests were great to read about, as a commenter pointed out there are other devices we need to know about and keeping on top of all that would be a full time job!

    At the moment, my plan is to use handsetdetection.com to tell me if the device is 1) an old mobile, 2) a newer mobile/smartphone, 3) a tablet or console or 4) something else (full fat desktop assumed). Based on this, I’ll server up stylesheets and media queries tailored to either 1, 2, 3 or 4 along with media queries to handle orientation and viewport size for 2, 3 and 4.

    Scott’s responsive images doesn’t appeal as it relies on Javascript, which I’m pretty sure a lot of old mobiles won’t support (and it’s those and slow connection speeds that would benefit from having small images the most).

    I hope to have a set up in place to test all this sometime soon… will blog about it.

  33. I seem to have a habit of typing ‘server’ instead of ‘serve’!

  34. Thanks everyone for all the comments; I’m definitely going to have to return to this topic. I found this site, btw, which tests different methods for downloading/hiding images using media queries: http://www.cloudfour.com/examples/mediaqueries/image-test/

  35. @David — I type server ALL the time as well. lol On responsive images — it actually serves the small one if JS isn’t available, and the large one is added through the data-fullsrc attribute. Scott says, “Ideally, this could enable developers to start with mobile-optimized images in their HTML and specify a larger size to be used for users with larger screen resolutions — without requesting both image sizes, and without UA sniffing.”

    @Peter — thanks for the link. Checking it now. (I set my MAMP server up to log over the weekend, so as soon as today’s deadline is over, I’m going to test some other ideas.

    It’s always interesting, isn’t it? :)

  36. Hello,

    I’ve since created a little JavaScript that swaps mobile images for desktop images. You simply but all the mobile images in a “mobile” directory and all the desktop images in a “desktop” directory. Pop the mobile images into the HTML and then the JavaScript will swap them. It’s a bit more basic than the Responsive Images script mentioned above, but it works pretty well.

    mimg

  37. […] Using Media Queries in the Real World Broken Links –  This entry was posted in delicious bookmarks and tagged CSS, html5, Javascript, mobile, tools, webdev. Bookmark the permalink. ← Bookmarks for April 25th Bookmarks for April 28th → […]

  38. This response is a bit premature. A few on this site have talked about server side processing, PHP, ASP, to handle this problem. That was my original approach also, but I’ve changed everything to JavaScript.

    The biggest problem with media queries is the lack of a default for browsers that do not support the technology. The best I’ve found so far to fix this issue is to write a parallel set of stylesheet for non media query browsers and they enclose the media query links in an IF statement like, if browser is greater than IE8 use these links, if browser is not greater than IE8 use these links. That approach totally sucks! How do you test for the proper versions of IE , FF , Opera, Chrome, etc at the same time?

    My site that uses JavaScript is not complete, but it is published if you’d like to look at it. The version on the web is for fluid design and it does not include the links when the page gets too narrow to allow for side navigation. I’m planning to publish a parallel site that is fixed width as soon as I finish the top navigation.

    I solved the default problem by defining all the style sheets but one as alternate style sheets. If the browser does not support JavaScript, the single non alternate style sheet becomes the default. If the browser does support JavaScript, and it runs correctly, the last step is to run through the list of stylesheet and activate / deactivate the sheets to select the correct one based on page width.

    I’m offering the script and also the MySSI process as freeware for non commercial use if anyone is interested.

  39. […] http://www.broken-links.com/2011/02/21/using-media-queries-in-the-real-world/ […]

  40. Thanks so much for suggesting putting the mobile css first and then the screen css. I was trying to work the other way around and was having a bunch of difficulty.

  41. […] and the desktop experience through media queries, an idea discussed by both Luke Wroblewski and Peter Gasston. Combining this approach with something like Adapt.js or 320 and up could improve performance for […]

  42. What I would like to propose is that added to the CSS3 spec is the ability to on a basic level control the DOM so that we can rearrange the source order of content.

    Relying on javascript or a server side solution to shift the source order of your site seems so restrictive.

    I believe CSS3 would be suited to this because it’s very much a layout/design design issue.

    I know this can be achieved on a basic level using positioning and floats, but it’d make life a lot easier if this was possible. Thoughts anyone? :-)

  43. @Glen, http://dev.w3.org/csswg/css3-grid-align/#source-independence

  44. […] and adding to the code that you have. But if you do choose this route, then you will need to start with the smallest resolution first, because this is the best practice for coding a responsive […]

  45. I am having trouble trying to build a site which relies on providing content based upon media query.

    Works great in IE9 and all other browsers. Display:none is not recognized in IE8 and lower. I’ve tried stripping down the page to loading just one of the 3 (mobile, tablet, and desktop) style sheets, and <IE9 displays the entire page content.

    Could someone see what I’m doing wrong?

    Here’s the page w media query:

    http://www.stageneck.com/multi.index2v.html

    Here’s the page with media query and my attempt to load a single css file for IE 8 or lower:

    http://www.stageneck.com/multi.index2vIE.html

    I don’t understand why IE 8 is not hiding the content I’ve set as display: none in the various css files.

    Thanks in advance.

  46. Kristi,

    I notice that at least one of the items you’re hiding in CSS uses a selector with ‘header’ in it, which is a new HTML5 element. Do you have the HTML5 JS shiv included in your Modernizr? This allows IE to style the HTML5 elements.

  47. I had pasted most of the javascript to the bottom of the page and

    Was there. I’ve moved it to the top, before the CSS call-ins, but that doesn’t seem to make a difference.

    I’ve updated the page. The Modernizr is from http://www.html5reset.org zipped package. I’ve uploaded the modernizr, jquery and functions javascript from that ZIP pack to the site.

    Unfortunately, I apparently know just enough to be dangerous :) so I’m not sure if other things should be changed and if everything is being started in the functions.js that should be.

    I so appreciate your reaching out to help!


  48. Sorry this dropped out of the above post.


  49. ! – [if lt IE 9]
    script src=“http: // html5shiv.googlecode.com /svn/ trunk/ html5.js“
    /script
    ![endif]–

    removed and spaced added to URL in an attempt to get this to show. Anyway, it’s in the header of the document now.

  50. […] and the desktop experience through media queries, an idea discussed by both Luke Wroblewski and Peter Gasston. Combining this approach with something like Adapt.js or 320 and up could improve performance for […]

  51. I am having some trouble trying to run a JS function only on mobile using your example:


    var screenWidth = (screen.width < 768) ? true : false;
    if(!screenWidth) {…}

    Essentially I have a list of bios that display normally on desktop, but on mobile they need to be in an accordion.

    This is what I have: http://jsfiddle.net/drFnc/

    Any suggestions on trying to get this to work?

  52. […] and up project page explains it like this “Inspired by Using Media Queries in the Real World by Peter Gasston, ‘320 and Up’ is a device agnostic,one […]

  53. @TrewKnowledge A better way to do JS media queries is with the matchMedia() method, like so:

    var screenWidth = window.matchMedia('(max-width: 768px)');
    if (screenWidth.matches) { ... }

    Your demo seems to be working fine.

  54. How can we load media query before standard css? Currently current styles is taking over media css files.

  55. […] to fit the different browser sizes of the various devices that they will be viewed upon, and to avoid the disconnect that often comes from thinking primarily about the desktop design and the rest of the responsive iterations as an afterthought (see especially Stephanie (Sullivan) […]

  56. […] fit the different browser sizes of the various devices that they will be viewed upon, and to avoid the disconnect that often comes from thinking primarily about the desktop design and the […]

  57. […] Using Media Queries in the Real World […]

  58. […] Using Media Queries in the Real World A good introduction to media queries as well as some implementation ideas and JavaScript based alternatives. […]

  59. […] Using media queries in the real world […]