Blog

Getting Started with Responsive Web Design

If you’ve been reading my posts for a little while then you may know I’ve been refreshing my website recently. I wrote a little bit about it a couple of months ago. One of the things I’m doing in this iteration that I haven’t looked at before is following the principles of responsive web design (RWD). If HTML and CSS are the primary mediums you work in then you’ll already know lots about RWD, and you’ll know that it certainly isn’t a new concept. If you’re more like me and you dabble in building websites from time to time then you’ve probably heard the term, but you may not know too much about it. Keep calm and read on.

Before I really even knew what RWD was all about it, I’d heard it described as a paradigm shift in web authoring equivalent to the one that occurred when we all stopped using the <table> element for layout and started throwing our content in <div>s instead, using CSS to position them correctly. This comparison is almost solely responsible for me being so late to the RWD party: I’ve always recognized why using tables to lay out content was not the best approach, but switching to CSS was not an enjoyable transition for me. To this day there are things I could easily do with a table-based layout that I’d struggle with in CSS (vertically centered content, anyone?). On top of that IE6 was prevalent at the time and it has a well publicised complete misunderstanding of how the CSS box model is supposed to work, meaning back in the day you basically had to code everything twice – once for non-Microsoft browsers, and then again for IE6, with a bunch of hacks in place to make things look consistent across all platforms.

I had no particular desire to put myself through that kind of learning curve again just for the sake of a simple personal site. Luckily I did decide to learn more, because RWD is not that scary. It’s true that it represents a paradigm shift in thinking, but under the hood it’s an evolution of the CSS skills you already have, not a revolution. Allow me, if you will, to take you through it.

What does it mean to for a design to be “responsive?”

To answer my own question, let’s take a step back and look at the problem that RWD addresses. I guarantee it’s one you’ve come across even if you’ve never built a website in your life.

When I first published something to the web, I assumed visitors to my site had a screen resolution of 640×480. Most did at the time. Some people had pushed the boat out and had hardware capable of 800×600, but if they visited then I just didn’t use their all of their available screen real-estate. No big deal. Eventually things evolved and it was safe to assume that the majority of people browsing the web were doing so in at least 800×600, and then 1024×768… and that’s where it seems to have stopped. If you look at most sites on the web today they’re built with a fixed horizontal resolution of about 900 pixels in mind. If your display is better than that, you get some empty space (the display I’m using right now has a horizontal resolution of more than double that, for example: 1920 pixels), and if your display is capable of less you get a scrollbar across the bottom. But that’s OK. It’s pretty unlikely your display is less than 900 pixels across these days.

But wait, is that true? A significant percentage of the people that read this will be doing so on a mobile device. If you’re using Apple’s ubiquitous iPhone and you’re holding it in a portrait orientation then you’re probably looking at this with a horizontal screen resolution of 640 pixels right now. Of course Apple is smart. They knew when they launched the iPhone that users would want to look at regular web content, so they built their software with that in mind. When you visit a typical desktop site on your phone it’s all zoomed out so you can see the entire page width, and then you pinch or double-tap to zoom in on the part you want to read. They also knew that web developers would be quick to catch up, so they built-in some standards that would allow for this behaviour to be overridden if the page was designed to work on a lower-resolution device. Designers (and companies) were all over this, and began creating two versions of everything – one that would look great with a horizontal resolution of 640 pixels for mobile devices, and a second that would work great on desktop computers.

This is great, but I think with the benefit of hindsight everybody can see how short-sighted they were being. The original iPhone had a screen resolution of 320×480, the iPhone 4 upped this to 640×960, the iPhone 5 uses 640×1136. Now let’s add the iPad into the equation. All those special iPhone versions of sites don’t look so great when you scale them up to a larger screen, so what do we do now? Design a third version of every site that works on tablets?

No. We stop the madness.

Clearly what we need here is one version of a website that works well and looks good regardless of the screen resolution and device that’s being used, and that’s the problem RWD solves. Crucially, it lets us do so in an intelligent way, by letting us use the same HTML but apply subtly (or even radically, if we want) different CSS to it depending on the dimensions of the users browser.

How is this magic possible?

At its heart this is extremely simple: stop using pixels to define element sizes and start using percentages instead.

Personally I find the easiest way to do this is to create an initial design that’s 1000 pixels wide. Then you simply divide by 10 to get a percentage. So a simple two-column layout would change from

#header {width: 1000px}
#navigation {float: left; width: 200px}
#content {float: right; width: 800px}

To

#header {width: 100%}
#navigation {float: left; width: 20%}
#content {float: right; width: 80%}

One quick note at this point: remember that we’re talking about percentages of the container element here. In the simple example above the container element is the <body> so it’s nice and simple, but if we have three 250px wide columns inside our #content element (with two 25px borders between them) then we can’t divide by the 1000px body-width to get a percentage, we need to divide by the 800px #content width.

250px / 800px = 31.25%

As humans it’s tempting to round numbers like that to, say, 31%. Don’t! It may look neater, but your computer will benefit from the added precision.

I could see this working for big resolutions, but surely it breaks down on small-screen devices, no?

Yes. But chill out, I’m only halfway done.

You’re right though, imaginary reader with all the questions. Using percentages is great and it makes sure we’re using all the screen real-estate we have available. I no longer have half a screen of whitespace on my full-HD monitor, but let’s think in the other direction. What about the iPhone in a portrait orientation. It has a screen width of 640 pixels. So our two-column layout is

= 20% of 640px = 128 pixels
#content = 80% of 640px = 512 pixels

And our three columns within the #content element?

31.25% of 512px = 160 pixels

Those are some pretty narrow columns. Even if you can’t picture it based on the number of pixels, I’m sure you can picture what four columns of content would look like across the screen of your phone. Not great.

Enter CSS media queries

Now that we have a design that uses the full width of the device it’s displayed on, CSS media queries are the second major device in your RWD toolkit. You may already be using them without even knowing it. Do you have a line like this in the <head> of your page?

<link href='/assets/css/main.css' rel='stylesheet' type='text/css' media='screen'>

That last part where it says media=’screen’? That’s a media query. You may have a separate stylesheet that’s used when the page is printed (media=’print’). But media queries can do so much more!

At this point what you do with your CSS depends on your direction of thinking. I build my CSS for big screens and then progressively adjust for smaller devices, so I’m going to use the max-width media query. If you’ve started from a small screen and you’re going to be progressively enhancing for larger then the min-width query will be more helpful for you.

Regardless, here’s a simplified example of what our CSS might look like with the story we’ve told so far.

#header {width: 100%}
#navigation {float: left; width: 20%}
#content {float: right; width 80%}
#content .column {float: left; width 31.25%; margin: 0 3.125% 0 0}

Let’s think about those three columns in the content area first. As we think about narrower and narrower screens those columns are going to quickly become too narrow to be useful, so let’s address that first.

If the user has a screen width of 800 pixels or less, then lets give them one column within the content area instead. We append this rule to our CSS:

@media screen and (max-width: 800px) {
   #content .column {float: none; width: 100%; margin: 0 0 30px 0}
}

And it’s as simple as that! Now users with a screen width of 801 pixels or more see three columns of content and everybody else gets a single column with the three pieces of content one on top of another.

From here, we just add additional snippets of conditional CSS for each step down in screen resolution that we care to define. We still have two columns at this point (#navigation and #content). That may not be ideal if the user has a screen width of 640 pixels or less. So:

@media screen and (max-width: 640px) {
   #navigation {display: none;}
   #content {float: none; width: 100%}
}

Now our is gone and we probably need a smart solution to get it back on lower resolution devices (maybe a button the user clicks to show/hide it), but you get the idea.

These snippets will work progressively. On a device with a screen width of 600 pixels, for example, both of the above will apply – 600 is less than 640 and also less than 800.

And that’s really all there is to it!

A note about mobile browsers

As I noted earlier, mobile browsers typically emulate a screen resolution higher than the one they actually have available to them (by zooming out). We don’t want this behaviour here because we’re now designing with mobile in mind, but we can address that by adding the following line to the <head> section of our <html>.

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

See it in action!

I’ve put together a couple of quick demos so you can see this in action. To get the most from it you should view the demo on a computer, and then drag the browser window to make it wider and narrower to see how the page responds. Links will open in a new tab.