retail-theatre_1424x397px

Responsibly responsive. Mobile First Responsive Design. Part 2

Posted 16 March 2012 12:15 PM by Bernard Lange

In Responsibly responsive. Mobile First Responsive Design - Part 1, we had a brief intro to responsive web design and why the usual desktop to mobile (top-down)  approach falls short, resulting in bigger and heavier sites. This post picks up where the first left off and expands on what could be the possible solution for providing your site with Mobile First Responsive Web Design.

Mobile First Responsive Design

By now, we know traditional responsive web design(RWD) is a no go.  Fortunately, all is not lost. We can still use RWD and still provide a good experience to less capable mobile devices. However, we need to shift our thinking to Mobile First.

What if we start with simplest, mobile friendly linearised version of the design and progressively enhance it with media queries and adaptive image techniques?
Mobile First Responsive web design
Reversed RWD process. Start with mobile layout and enhance for wider screens
So, if you start narrow and reposition, enhance and fix for wider screens. Eventually, your CSS might look like this:
// style.css
... basic linear layout,
   typography and styling

//resolution adaptations
/*resolution adaptations*/
@media (min-width:320px) {
   ...styles for 320px and up go here
}
@media (min-width:480px) {
   .logo {
   		float: left;
   }
}
@media (min-width:780px) {
	.aside, .main {
		padding: 0 2%;
	}
	.main {
		width: 62%;
		float: left;
	}
	.aside {
		float: right;
		width: 30%;
	}
}
@media (min-width:960px) {
	#wrapper {
		width: 70%;
	}
}
Taking advantage of the fact that media queries are ignored by devices which don't understand them, we then serve basic layout to those devices/browsers and enhance for media-query capable ones. Compared to the usual RWD approach mentioned above, the main difference lies in how the tweaks are done. I'm not disabling desktop styles, as with the usual top-down RWD approach, but rather, working bottom-up and adding new layout styles as the available canvas gets bigger.

Show IE some love (yes, I've actually said that)

Sharp-eyed readers will quickly notice that such approach leaves Internet Explorer which does not support media queries (until version 9) out in the cold, served simplest, single column low-fi version intended for least capable devices. We don't want that to happen, do we? After all, it's not the IE browser but users who use this browser that we want to support. This problem can be alleviated in multiple ways.

1 - Beware of IE "understanding" media queries

Remember the underscore hack? Exploiting IE 6/7 CSS parser vulnerabilities can be used today as well. As research on media queries by Opera shows, IE ignores certain media query constructs it does not understand and unconditionally applies wrapped styles:
@media screen, all and (min-width: 300px) {
  .column {
      float: right;
  }
}
This can be a source of weird bugs is what I'd like to point out. And in case, you wonder why can't we exploit this to our advantage, making IE happily digest all our desktop styles? Well, this media query bug has been fixed in IE8, so it's not an option.

2 - Media queries JS polyfill

Common approach to IE, is to plug its missing capability holes with JavaScript counterpart. This isn't different in case of media-queries. You can use respond.js to make IE understand simples max-width and min-width media queries. It's small and fast. Just drop it after your styles:

<link rel="stylesheet" href="/css/style.css">
<script src="/js/respond.min.js" ></script>

If your media queries are complicated, you can use css3-mediaqueries-js, but be warned, since it's more feature rich, it's bigger and slower.

 Of course, if JS is not available because say, the corporate proxy stripped it, IE will display mobile layout.

3 - Conditional comments

If you're a bit like me, and putting more JS burden on the already troubled IE gives you the shivers, then hey, the good news is that there are other options! One might be to provide IE with conditionally served ie.css which would contain a copy of styles that constitute the desktop layout version.
<link rel="stylesheet" href="/css/style.css" media="all">
<!--[if (lt IE 9)&(!IEMobile)]>
<link rel="stylesheet" href="/css/ie.css" media="all">
<![endif]-->
But this approach has two disadvantages. Firstly, IE will download two CSS files, majority of which it will not understand (due to queries). Secondly, it forces us, as developers, to maintain duplicate styles both in style.css and ie.css.

Alternatively, it might be, that the number of your break points is equal to one, and you could move media query to link element and take advantage of slightly different approach described originally by Jeremy Keith.
<link rel="stylesheet" href="/css/basic.css" media="all">
<link rel="stylesheet" href="/css/style.css" media="all and (min-width:320px)">
<!--[if (lt IE 9)&(!IEMobile)]>
<link rel="stylesheet" href="/css/style.css" media="all">
<![endif]-->
This removes the burden of duplicate styles, but is less flexible, assuming one breaking point. Please note, that to basic styles had to be moved to separate file, to be served to non-media query capable browsers.

4 - CSS processors to the rescue

Using SASS we can try and alleviate duplication issues. First, let's split further our styles into reusable parts:
//basic.css
... basic linear layout,
  typography and styling

// style.scss
@media (max-width:320px) {
       import "up-320";
}
@media (max-width:480px) {
   import "up-480";
}
@media (max-width:780px) {
  import "up-780";
}
@media (max-width:960px) {
  import "up-960";
}
@media (max-width:1200px) {
  import "up-1200";
}
// ie.scss
@import "base";
@import "up-320";
@import "up-480-up";
@import "up-780";
@import "up-960";
Notice small snippets related to different resolution ranges are imported. This allows us to keep any wider resolution enhancements in one place, and reuse them in both style.css and ie.css. Sample use might be:
<link rel="stylesheet" href="/css/basic.css" media="all">
<link rel="stylesheet" href="/css/style.css" media="all and (min-width:240px)">
<!--[if (lt IE 9)&(!IEMobile)]>
<link rel="stylesheet" href="/css/ie.css" media="all">
<![endif]-->
As a result, media query blind browsers, will download only basic styles. More capable ones, will get basic.css and style.css using styles that matches their screen size. And our venerable oldIE friend (sans Mobile IE) will get the non-responsive, yet desktop-optimized styles.

There's always a but

One might argue that it's still not mobile friendly enough. What's the point of serving styles for resolution bigger than 480px for mobile phones? Well, one option will be to further split down the styles based on media query ranges they contain. E.g.

<link rel="stylesheet" href="/css/basic.css" media="screen, handheld">
<link rel="stylesheet" href="/css/small-screen.css" media="all and
(min-width:320px) and (max-width: 640px)">
<link rel="stylesheet" href="/css/big-screen.css" media="all and (min-width:320px) and (min-width: 640px)">
<!--[if (lt IE 9)&(!IEMobile)]>
<link rel="stylesheet" href="/css/ie.css" media="all">
<![endif]-->

This is the approach taken by Yiibu, a well recognized mobile web development agency. You get more details in Stephanie Rieger's"Pragmatic Responsive Web Design" presentation. To decrease the number of HTTP requests, this approach could be taken a bit further with a little server side detection (involving something like the WURFL database or Device Atlas to check browser resolution), we could for instance, modify the markup a bit and serve just a small screen version:

<link rel="stylesheet" href="/css/basic.css" media="all">
<link rel="stylesheet" href="/css/style.css" media="all and (min-width:320px)">
<!--[if (lt IE 9)&(!IEMobile)]>
<link rel="stylesheet" href="/css/ie.css" media="all">
<![endif]-->

 or combined (small+big screen) version

 <link rel="stylesheet" href="/css/basic.css" media="all"> <link rel="stylesheet" href="/css/style.css" media="all and (min-width:320px)"> <link rel="stylesheet" href="/css/small-and-big-screen.css" media="all and (min-width:320px) "> <!--[if (lt IE 9)&(!IEMobile)]> <link rel="stylesheet" href="/css/ie.css" media="all"> <![endif]-->

but that would give us headaches if any kind of content delivery network (CDN) is involved. Well, there is no silver bullet, but you know that, don't you?

Responsive images are non-trivial

There's no single best solution that I can point you to. Quite the opposite, there are numerous attempts to solve the images problem from a responsive web design perspective. When it comes to adaptive images, everyone has their own opinion. In case, you'd like to know some of the more popular opinions, here's a couple of posts that may help to give you a fair idea: Of course, the web standards body are involved in that process, e.g. discussing approaches similar to <video> element, where different images could be specified for different screen resolutions.

<picture alt="angry pirate">
<source src=hires.png media="min-width:800px">
<source src=midres.png media="network-speed:3g">
<source src=lores.png>
   <!-- fallback for browsers without support -->
   <img src=midres.png alt="angry pirate">
</picture>

5 - Server-side UA detection

Personally, I'm leaning towards a server-side reliant solution. Detect on the server side, the kind of browser you're dealing with, mobile or desktop (using WURFL and detecting capabilities or just by taking an educated guess that anything that does not match the desktop user agent is probably mobile). When unsure, default to mobile. Simplest approach might look similar to:

$url = "mobile-size.jpg";
if (isDesktop(UA)) {
    $url = "desktop-size.jpg";
}
render( <img src="$url"> )

 I know this does not sound like the most robust solution and to some of you UA detection is plain dirty, but frankly, there isn't an  ideal solution yet. Major arguments against UA detection is that you'd need to maintain list of UA's. Well, yes and no. In this approach you detect desktop and err on the safe side, serving mobile url of image when unsure. After all, how often is a new desktop browser launched, compared to new mobile devices?

You might argue that it does not take user screen size into account. But let's be realistic, are you going to provide images in four different sizes? (like 240px, 320px, 460px, 640px?) I highly doubt that, so I suggest you pick two sizes eg. 320px and 640px, one for mobile and one for desktop. Use max-width:100% to account for screens smaller than chosen mobile image width. Job done, go get yourself a beer now.

6 - Client-side screen detection

Still here? Well, there are other options. To show you how it's on the other side (pun intended), let's take a look at approach taken by Boston Globe.

On the server side, render images with src attribute set to mobile version of the image. Additionally, add url for desktop version within data-attribute:

<img src="images/mobile-size.jpg" data-fullsrc="images/desktop-size.jpg">

 On client side, JS (placed eg. in head) is used to detect screen size with window.screen.width and decide if desktop version should be used (this decision is saved in a cookie). If so, the src attribute of images is changed to desktop counterpart via JavaScript.
You'll probably notice that the image tag has to already be in markup for JavaScript to be able to mangle with its src. That also means, that browser has already started downloading the image. This is when the cookie comes in to play. When browser asks server for mobile image url, it sends the cookie along with the request. Server needs to be configured to react to this cookie. If if indicates that desktop is used, instead of the requested image it will send back 1x1 spacer gif. Later, when JS kicks in, desktop url will be requested.
The cookie trick was supposed to prevent desktop browsers from downloading both mobile and desktop version. But you know what, this approach broke.

At the end of the day, pick whatever looks most suitable to you. Or if you don't care, stick to original fluid images idea. Least performant, but mostly works (save Blackberries) and is trivial to implement.

Last words on JavaScript treatment

Media queries touch only CSS side of the mobile layout formula. But being responsibly responsive means serving only this much JS as device can handle. Since there's no mechanism similar to media queries for JS, until matchMedia is widely supported (and it won't happen any time soon).
One has to either make assumptions regarding device capabilities on server side (choosing e.g. to not to serve JS to older Blackberries with really slow and buggy JS support) or to feature detect on client side and load scripts as needed using e.g. yepnope conditional script loader.

Can I use it today?

As you can see, being responsibly responsive might involve taking some hurdles, but luckily, it's not only me, who noticed standard RWD approach could be unsuitable for mobile. Smart folks like Jeremy Keith and Andy Clark came up with the forked Mobile Boilerplate named 320 and Up which takes Mobile First approach and enhances progressively. You might want to give it a go in your next project. Also, take a look at some of the sites that were built using Mobile First Responsive Web Design like Nokia BrowserYiibuBoston Globe or Ethan Marcotte's homepage

Which way should you choose? Definitely start with the mobile version and enhance for wider screens. Embrace IE (in any way proposed), serve mobile images by default and try to load your JS conditionally.

Remember though, responsive web design isn't a silver bullet. If you create your site for mobile, speed matters. If you can cut on HTML, images, CSS and JS, do it. Even if that means server side UA detection, delivering same content to mobile users at great speed, is what matters most.

Bernard Lange

Archive