January 9, 2012
Retro-fitting media queries and mobile optimization
or, “a practical guide to not starting over”
Increasingly, clients who are otherwise happy with their websites are requesting “mobile versions.” This usually means they’d like to have a simplified, easily-navigable, one-column site that looks great on iphone and android. Over the past year when I’ve fielded these requests, I’ve taken the opportunity to explore media queries and the principles behind responsive web design.
The basic idea of responsive web design is that having a “desktop version” and a “mobile version” isn’t nearly enough. With the increasing popularity of tablets, e-readers, and smart phones in dozens of different screen sizes, there should be one version of your website that adapts (responds) to the device on which it’s being viewed. In other words, make one site look as if it were built for every device imaginable. And do this without changing the original HTML, and without duplicating content across various subdomains.
It’s a really, really great idea, and I’m all for it.
In a perfect world of unlimited time and resources, all of my clients would pay me to scrap their current site and use one of these excellent new frameworks to build a new site. However, that’s simply not realistic sometimes. Sometimes I need to take the shortest path possible to create a good mobile experience. I need to retro-fit older sites with responsive design without completely scrapping the code and starting over. After all, I’ve been coding with semantic markup and CSS for longer than the iphone has been around. Surely I don’t need to completely start over, right?
I do want to mention first that there are drawbacks to the steps below. I am overriding the main styles with the mobile styles, which can lead to more HTTP requests and heavier page weight than is necessary on the mobile side. If you need to watch your traffic down to the kilobyte and millisecond, this probably isn’t for you. But if you're dealing with a small budget and a low-traffic site, hopefully this will save you a bit of time. At the end of the day, it's all about the users. If you can in good confidence produce a mobile experience on top of an existing design, your clients are trusting you to make that decision.
OK, without further ado…
HTML
First, you need to add a couple of things to your HTML header in order to give mobile browsers some instructions.
Add the following meta tag to your <head>. This says “Display the page at the real size of the device, or 100%, and disable zooming.” Another way to look at this is that if the device is 320px wide, only the top left 320px of your site will display on initial page load.
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
Next, it’s nice to add a few Apple-specific icons to the header. So when a user tries to save the site to their phone’s home screen, they’ll see your icon instead of a tiny screenshot of the page. By default, the iphone will add a curved glossy overlay to the icon, but adding “-precomposed” to the end of the filename prevents that from happening. I prefer to use my own photoshop work, so that’s pretty standard for me. (Currently, there's no way to duplicate this functionality in Android.)
<!-- Favicon ========================== -->
<link rel="shortcut icon" href="/favicon.ico"/>
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="/apple-touch-icon-precomposed.png">
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/apple-touch-icon-72x72-precomposed.png" />
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/apple-touch-icon-114x114-precomposed.png" />
As far as the HTML goes, that’s all you need to do right now.
CSS
This is where the magic happens. There’s no specific rule for where to put your ‘breakpoints’, or the specific browser widths that make your media queries override your main site styles. To keep this as simple as possible, we’re only going to specify one breakpoint at 767px, which is just a pixel smaller than the ipad’s skinny side. So your site will still display the unaltered desktop version on ipad, but will use the mobile styles on anything smaller than that. If you want to go crazy with multipe media queries, there are several examples for inspiration here.
At the bottom of your main CSS file, paste this:
@media only screen and (max-width: 767px) {
/* simply type normal CSS between the media query brackets
}
Then, I start with 100% on my body tag, as well as a bit that says “when you rotate the device, don’t try and change the type size. That’s annoying, stop it.” And since I tend to use background images in many of my designs, I replace them with solid colors here, since only a little bit will show through. Finally, I give a little margin to my main content area and clear the width. Also keep in mind that both android and iphone use the webkit browser. So if you want to use propritary CSS3 properties like -webkit-box-shadow, go for it.
body{
width:100%;
-webkit-text-size-adjust: none;
background: #b3c9e1;
}
.main-content-area{
width:auto;
margin:10px;
}
Then, I use two global resets to categorize my other elements into what displays and what doesn’t. The first simply hides things like a second navigation area in the footer, a sidebar full of unnecessary links, and things that you tried to talk the client out of when you designed the site originally. The second clear widths, floats, and any other styles from the existing layout. You’ll likely add both selectors and options to this as you go, but this will give you a good start.
.footer-navigation,
.annoying-sidebar-elements,
.necessary-evils,
.other-stuff-that-isnt-necessary-for-mobile{
display:none;
}
.header,
.navigation,
.content,
.important-sidebar{
display:block;
width:auto;
padding:0;
margin: 0;
border:0 none;
background:none transparent;
}
Next, stack up your navigation:
ul.navigation {
display:block;
width:100%;
margin:10px 0;
padding:0;
float:none;
list-style:none;
}
ul.navigation li {
width:100%;
float:none;
}
ul.navigation li a{
display: block;
padding:10px 6px;
width:auto;
text-decoration: none;
color:#fff;
background: #0C4583;
border-bottom:1px solid #2e6096;
}
Finally, this little gem tells all of your images not to display any bigger than the width of their container element. Just like that, all of your images are responsive, too:
img{
max-width:100%;
}
Javascript
Typically, “content first” is a good rule for the mobile web. With what you’ve done so far, you’ve likely got a long list of navigation that’s taking up most of your screen. To put this below your content requires a little javascript. In english, this does the following:
- Make a clone of the navigation and store it in a Javascript variable
- Calculate the width of the window
- If the size is less than 767px, remove navigaiton and place it (via the variable) after the main column. If it’s greater than 767px, remove it and place it back where it was. (We had to do this because for testing, we simply grow and shrink the size of the window.) If the user does that, this script still works.)
<script type="text/javascript">
var nav_is_at_top = true;
var $nav = null;
function movenav(){
size = $(window).width();
if(nav_is_at_top && (size < 767)){
$(".navigation").remove();
$("#mainColumn").after($nav);
nav_is_at_top = false;
}
else if((!nav_is_at_top) && (size >= 767)) {
$(".navigation").remove();
$("#logo").after($nav);
nav_is_at_top = true;
}
}
$(function(){
$nav = $(".navigation").clone();
movenav();
$(window).resize(function(e){
movenav();
});
});
</script>
That’s all!
Of course that’s not all.
The web is messy, and likely, so is some of your old code. But with this as a starting point, you can now override anything. Just keep in mind that long and ugly selectors in your main CSS file will still need to be long and ugly in your media queries; the rules of CSS cascading still apply. Once you’ve got the main structure done, just browse through your site and start tweaking things. Give your form fields extra padding, remove pesky widths when needed, and give all of your links plenty of room for fat fingers to make mistakes. You can swap out background images, make fonts bigger or smaller, etc. There are as many ways to optimize a site as there are ways to design a site in the first place, so be creative, and enjoy.
PS: If you're thinking "that's nice, but can I just hire you to do it for me?", the answer is yes. Resize your browser window or visit any of these sites on your mobile phone to see samples of my media query work. These vary in complexity from a fully responsive real estate search app to a simple news site. Feel free to contact us for details, or find me on twitter @kaseykelly.
- reoclevelandhomes.com
- weserveseo.org
- pyohio.org
- lepirealestate.com
- akroncitycouncil.org
- kellyarchitectural.com
- khi.org
- clevelandmarathon.com
- fabri-form.com