Steve Taylor photo

Responsive design 101

Recently I built my first responsive website. The project had a really tight deadline, so I didn’t have much time to experiment. I did some research and I think I hit upon some crucial tips that saved me a lot of hassle. I thought I’d document what I’ve learned from this first foray into adapting for mobile devices, and perhaps save someone else some time.

Before I start, just a word on my title—“responsive design”. Actually, this post is more about responsive development. I’m chiefly a developer, and the project I just worked on was not designed with responsiveness in mind. No doubt, because of the flexibility demanded by responsive design, if you’re a one-person designer/developer, a lot of this may be much easier than it might otherwise be. I’m looking into responsive design workflow at the moment, and working with the designers I work with to move in this direction. But my advice here is coloured by my having to create a responsive site without having any input into the design.

Not only that, but I actually didn’t know if I would get time to include responsive CSS. I built the plain “desktop” version as I would normally first, then, finding I had some spare time left, added the responsive stuff. So this advice will probably be helpful to anyone “retrofitting” responsiveness. It’s not the ideal “mobile first” way of doing things, but it’s how things happened for me.

OK. First things first.

1. Don’t forget the viewport meta tag

If you’re building a responsive site, you’ll need this in your HTML header:

<meta name="viewport" content="width=device-width, initial-scale=1">

This will prevent mobile devices from showing the full “desktop” version, zoomed out. More details here.

2. Break to the design, not the device

Breakpoints are widths at which different CSS rules kick in to mould your layout according to the available space. Typically you’ll use a media query in your stylesheet to define a breakpoint, like this:

@media only screen and ( max-width: 480px ) {
	#content {
		float: none;
		width: auto;
	}
}

This will stop the element with the ID content being floated with a specific width at screen widths below 480 pixels.

Now, many responsive frameworks, and many popular media query snippets, include breakpoints that correspond to various different device screen widths. But as one of the better tutorials on responsive design points out, this approach is fundamentally flawed. It’s impossible to keep up with the ever-changing screen width landscape.

A much better approach is to see where the design itself starts to break, rather than breaking according the device screen widths.

For me, starting with a fixed-width design that wasn’t built with responsiveness in mind, the first breakpoint is basically when you start to lose more than a few pixels off the right side. Once this point kicks in, my media query kicks in, and my fixed-width design becomes roughly “liquid”. The main wrapper width is set to 100% or auto, and the various markup sections are adjusted to flow with the screen width.

NOTE: I realized later that you can build this fluidity right into the “default” styles by doing something like this:

#wrapper {
	width: 100%;
	max-width: 950px;
}

These adjustments can work quite well for a bit, but then as you keep contracting the width, you’ll hit another point where things start to break down. (At this stage I just adjust the width of a desktop browser window to test things. There’s no substitute for looking at actual devices when it comes to proper testing, though.) Note the screen width at this point, and create  a new media query.

My experience landed me with 2 major breakpoints, which—while I’m not really being device-specific—I roughly equate to “tablet” and “smartphone”. So, there ended up being 3 versions of the layout:

  1. “Desktop”. The original fixed-width design.
  2. “Tablet”. A more fluid version, for tablets and maybe people on desktops who don’t maximize their browser window.
  3. “Phone”. Adapted to the smallest screens.

It’s the final version where many of the typical “responsive” tricks kick in:

  • All floating is removed
  • Most lists become vertical instead of horizontal
  • Layout is generally reduced to a single full-width column
  • Images and other media are generally set to max-width: 100%
  • The main nav at the top is collapsed, and made accessible by a “navicon”

And that, for me, worked very well.

3. Proportional images

You’ll quickly get the idea that images in a responsive design should be set to max-width: 100%, to prevent images wider than a small screen from overflowing. However, if the img tag has a width and height specified in it attributes, this will result in the width being constrained proportionally while the height remains fixed—leading to squashed images.

The solution is simple:

img {
	max-width: 100%;
	height: auto;
}

More details from 456 Berea Street.

4. Lazy image loading

So much for responsive layout. However, there are other issues related to adapting to mobile devices, and one of the most prominent is page loading speed on slower connections.

Since the page isn’t rendered until images are downloaded, images—especially large ones, or multiple smaller ones that can’t be included in a sprite because, say, they’re on different servers—can really slow things down. One technique to work around this is to serve a placeholder (say, a 1 pixel transparent image, sized appropriately), then use JavaScript to switch in the actual images once the page has otherwise fully loaded.

I’ve written a post about this, known as “lazy” or “deferred” image loading.

5. Adding heavy features with JavaScript

An extension of this is to use media queries in JavaScript to conditionally load “heavy” features such as image carousels.

You can mimic CSS media queries in JavaScript either with jQuery, or by using the mq() method in Modernizr. Remember that this is still just testing screen width—it doesn’t necessarily say anything about connection speed. But sometimes it’s worth erring on the side of caution, and only serving heavy features to wide screens (which are more likely to have fast connection speeds).

In the project I just did, there was a largely decorative image carousel on the home page. To keep the mobile version light, I served a simple static image by default. Then, using mq() from Modernizr, I constructed the image carousel entirely with jQuery—but only for screens above a certain width.

Now of course, this is a limited instance of a wider issue. Even if a mobile device and a desktop share the same connection speed, images for the smaller screen obviously needn’t be as big as those for the desktop. Is there a standard way of reliably serving up images appropriate to the device? In a word, no. Not yet. It’s worth looking into what you can do, to tackle situations where the images are heavy and/or the project needs to perform particularly well speed-wise. But don’t sweat this too much. Even the experts admit it’s an insanely complex issue.

6. Workflow

What next?

  • Evolving workflow to accommodate responsive design is the next step, and Stephen Hay’s book should prove valuable.
  • Of course there’s the still-debated but hard-to-ignore “mobile first” philosophy.
  • No doubt, shifts in design towards a more iterative process that ditches the old linear “wireframe > PSD > build” process may be necessary (see Style Tiles).
  • In-browser design looks to be another important part of the responsive puzzle.

7. Grids?

Responsive design often goes along with grid frameworks. I’ve been meaning to try out grids for a while, but the projects I work on are typically too idiosyncratic to make them worthwhile.

In any case, here’s two good posts that have kept me clear of over-complex “grid systems”:

8. Tools

Here’s a few tools I’ve found useful, or which look promising:

  • Window Resizer for Chrome. Great for gauging your breakpoints.
  • Firefox Ctrl-Shift-M. Just hit this shortcut in Firefox for checking out some typical device screen sizes.
  • Screenfly. View at different screen sizes online.

OK, that’s it for now. Just a few tips for getting going…