Responsive web design and layouts

Recently I've been doing a lot of responsive sites for clients. They're fun and often challenging things to work with; opinions and solutions from various developers and designers scattered liberally throughout the internet. So I suppose it's about my turn to chime in on it all.

Why responsive?

My general ethos with layout stuff on the web is that everything needs to come from your stylesheets. Device responsiveness is a design-level feature, and I don't believe it has a place in procedural code or should influence the semantic meaning of your documents in any way. You're simply providing a pretty view of your website, and the place for that is CSS. Writing separate sites is cheating, and also extraordinarily time consuming and hard to maintain. I'm not interested in doing user-agent sniffing and serving special stylesheets to a limited range of devices currently in the market. I'm even less interested in writing JavaScript to manage these things - it's slow, clunky and not nice™ - compare any JavaScript animation against CSS transitions running on an iPhone or Android device and you will see a marked difference on that little CPU (indeed, I myself have taken steps to correct this when creating more advanced animated UIs).

Doing it wrong

With that goal in mind, if experience has taught me anything it's that designing to specific devices is a bad idea. Often you will get briefs from clients with 5 or so attached layouts stating that they want their site to look one way on desktop, another way on iPad in landscape, another way in portrait, and the same again for both phone orientations. The first thing you'll notice when starting off like this is that device resolutions overlap widely. In particular Apple devices (as that has annoyingly become the de-facto standard) but when you start including other brands, makes and models in the mix it quickly gets dirty. But let's just focus on iDevices for now.

  • The older iPhones are lower resolution in portrait than iPhone4+ are in landscape. That overlap is going to cause problems.
  • iPads are lower resolution in portrait than iPhone 4's and above are in landscape. Thus we also have to query the display density to differentiate between tablets and phones.
  • The iPhone 5 is wider in landscape than any current iPads are.

It becomes very confusing very quickly if you're thinking as you go. You can of course immediately start making concessions to make your life easier. Most people wouldn't worry that you don't see a landscape layout on iPhone 3 or would pick their battles elsewhere. We also still haven't considered next-gen displays which we know are coming with 220dpi screens: the MacBook Pro already has one and it's just a matter of time before we need to add min-device-pixel-ratio: 2.5 to complement the standard min-device-pixel-ratio: 1.5 used currently. This is fine, I guess. But we still haven't thought about any other platforms.

The Android display mix is pretty crazy. At time of writing, you could be looking at anything from 320x240 @ 120dpi to 2560x1600 @ 320dpi! Windows phones have a more restricted set of resolutions, but the large 1280 displays will be difficult to fit into the mess of CSS you've probably built by now.

Doing it right

So. My suggestion is quite simple - don't build for devices, build for resolutions.

What do I mean by this? Use your designs as a goal, and simply shrink your page down gradually as your design dictates. Don't focus on switching a multilevel menu out for a dropdown @ 480px, instead just start altering the layout at the points it needs to change. If you need to make an adjustment at 487px for some element and another at 483px for another, it doesn't matter. You are doing it right. You are making sure your site works at every concievable resolution, not just the ones currently used by the most common devices in the market. No matter what happens in the future, no matter what size screens the next generation of phones have, your site will still look good.

This site is a good case study. It performs a combination of font-size steppings and layout adjustments as needed to bring it down to mobile size. The font controls can be one-liners if you define your base line-height style as a float:

body {
    font-size: 16px;
    line-height: 1.5;
}
@media only screen and (min-width: 880px) and (max-width: 959px) {
    body { font-size: 96%; }
}
@media only screen and (min-width: 820px) and (max-width: 879px) {
    body { font-size: 92%; }
}
@media only screen and (min-width: 760px) and (max-width: 819px) {
    body { font-size: 88%; }
}

... and so on. But because this sort of technique only works under particular conditions, this brings me needly to:

Layout units

I have had a great deal of interest in this topic lately. Getting your layout system, maths and so on correct in the beginning can save you hours towards the end of something and days in maintenace later. Another developer and I tried out several techniques across about 8 different projects over the course of the last year or so. The short version - use ems.

But why? Of course keeping the structure of your site as simple as possible is a factor, and also key. Many would argue that ems become complicated to use, and this can be true. But lets look at the advantages and disadvantages of each technique. In fact, this kindof doubles as a brief history of web layout techniques:

px-based layouts

Ahh, pixels. Pixels are great. You measure your designs in Photoshop, type in the same numbers, and hey presto website. But of course this simple method has a tradeoff, and that tradeoff is flexibility. Because you've given your site exact dimensions, it's always going to be that wide, no matter what - thus aptly naming it a "fixed" layout. There are lots of old websites out there, originally designed to be centered in about half the window, that these days show as a tiny rectangle stretched down the middle of your giant 32" or 24" or even 15" monitor (this website was one of them). If you go down the road of pixels, you'll be coming back someday soon to redo them.

Then there is the issue of font scaling. Boxes given fixed font widths don't scale when the browser font size is changed. As a result, previously workable layouts suddenly explode, overflow and stagger down the page horrendously. Modern browsers still do this today. "But who changes their browser font size?" I hear you whine? People who don't see well, jerk. And people with small screens and people with large screens sitting back in their couch and people who simply don't like the defaults. Just because you aren't one of them doesn't mean you should ignore them. There is a path partway out of this problem - you can set a base fontsize in pixels... but then you've effectively turned of visual accessibility and disabled zooming for those on more lightweight mobile browsers (Opera Mobile, some Symbian & Blackberry browsers) or older desktops (IE6 & 7 are the only ones I can think of). The accessibility is clearly more important than the browsers, except perhaps if you have a large userbase in the developing world where cheaper phones have the widest markets.

Using other absolute units like pt or the newly added rem suffer some of the same issues, although rems scale fine they only have recent support and so you always end up needing to do them in tandem with px anyway.

%-based layouts

Percentage-based units are where responsive design started. When combined with floats, they make great columns and I still use them for this purpose today. That's about the only place actually, in my grids. This is called a "fluid" layout, because the width of the elements on the page is related to the width of the screen. Stuff gets narrower when the screen does, and it keeps its proportions. Zooming also works consistently, which is great.

Unfortunately when using them in smaller areas alongside text, edge-case things like orphans and widows can become annoying to deal with. When the wrapping areas shrink, floated content like images that have been percentage-scaled don't scale down with the text near them, just as pixel-scaled ones would. Fluid layouts also have most of these same problems as fixed ones when it comes to old browsers and text scaling; the text will flow out of its containers and break the layout and zooming won't work well.

All in all they are pretty great and easy to understand if coded well. They are still missing our key element, however - easy resolution-driven scaling of all their contents.

em-based layouts

With ems you can drive your whole layout - text, images, embeds and the containers that position them around each other - in a reliable and connected way. As font is scaled, whether by browser zoom or user preferences, every element related to and positioned nearby that text can adapt as well.

But there are some complexities we are going to have to iron out first. Font sizes are the oldest way of scaling things out there, and support is (near) perfect. Hello, IE7! With their problems with greatly exaggerating text size (and thus zoom), IE6 and 7 can't even get that right. There is a way around it however, as detailed in full here we can use the good old star-hack to set those baselines consistently.

I take this one step further, because using a default size of 16px is fairly different to work with. You could do it of course, but then there would be a lot of complicated maths involved in converting all your designs into multiples of 16. So I sometimes like to set an easier baseline, and then set my content font sizes more explicitly. Here it is in LESS.. you should easily be able to follow the maths to write your own:

But actually, since we are using a preprocessor we can get around the maths problem too (and if you aren't, then you are wasting hours of your day and being incredibly stupid about the way you work). There is still that additional complexity of nested elements, such as when you want to style something like a <li>. What happens when you nest a 1.2em <li> inside another? Of course 1.44em makes sense, but it's not useful. You can get around this sort of issue easily with some simple maths. In fact, I even style my images using em now so that they retain their proportion to the text (well, I style my <figure>s and make the images have 100% max-widths, but semantics :p). To do so, just divide your desired unit by the font size of the element above it, convert to ems and hey presto you have layout perfection again:

This doesn't need to be done in pixels, by the way; that's just a default. So long as the two units you are passing in are the same, it will all work out fine. We just want to divide two unitless numbers and then multiply by 1em.

Conclusions

Defining your layout in ems and dropping text size can take care of a lot of scaling. Approach columns thereafter as needed to bring things down (using a grid system will really help with this, as will defining your HTML in the order it should be read.. which again you should be doing for accessibility anyway). In more complex designs you will probably still have a few odds and ends to tie up, but that work should be fairly limited.

One of the things I find when working in this method is that your CSS ends up cleaner. Instead of making many little adjustments trying to get things to match a design exactly, you end up with broader rules which handle most of the work very readily. In the case of this site I really just bring down my column layouts once they no longer fit side-by side, but this is a fairly simple design.

You might have to fight some clients, of course. They might need it explained that the site differs from designs on their precious iPhones for good reasons. But this stuff is really design-level. Educate your designers, have them mock up mood boards and design components instead of explicitly designing 5 different websites. Let them have the conversation. After all, it's less work for them too!