So this week marks only tiny changes visually, but some pretty major adjustments under the hood. Things are starting to dance!
But first, a note about my process vs. mobile first; along with buzzwords like "responsive" and "agile," you've probably been hearing the term "mobile first" being thrown around. Despite Luke Wroblewsk's entreaties and what is an arguable best practice, I decided NOT to start with a "mobile first" approach, but from what I (and presumably most designers) know best: the desktop.
While it is undeniable that the mobile web is fast outpacing the desktop, and there are some definite benefits and best practices to be found in a true mobile-first approach (including things like conditional loading, proper content planning, etc.), I believe in general you should never put a specific context first; you always put the USER first. Know thy user, and thy kudos shall follow.
In most cases this means more work for you. Tough nuts. Suck it up and put on your big-kid pants, 'coz you're not going to win any fans by ignoring your user or planning your content poorly.
However, as I've observed before, this project is a simple test meant to help me (and maybe you) to figure out how to approach the world of RWD from a more traditional web designer's vantage point. We are the users, and in the interest of improving our grasp of the tools and principles, we're going to put a few arguable best practices aside for the moment, start from the context that will best support our learning, and just git 'er done.
However, as I've observed before, this project is a simple test meant to help me (and maybe you) to figure out how to approach the world of RWD from a more traditional web designer's vantage point. We are the users, and in the interest of improving our grasp of the tools and principles, we're going to put a few arguable best practices aside for the moment, start from the context that will best support our learning, and just git 'er done.
Ch-ch-ch-changes
Before we get down with all the exciting updates in this week's installment, let's take a little look at the new test site:
Ooooh, kitties! Yes, I've gone over the top with the visual design now, courtesy of placekitten.com, which has a little more personality than placehold.it. While I like flickholder.com in theory, the initial load time to pull in an image seems pretty long for my tastes (plus who doesn't love kittens?). Anyway, image placeholder services can be great when you have no idea what your visual content will be, but you need to show... something. At a specific size. It's like visual lipsum.
The second, and possibly most important thing, is that The Hideous Footer is a little bit less hideous now - it is still position: fixed, but it now spans the entire width of the page, looking a little more integrated. Whew!
The next thing you'll notice, if you play around with the browser window (you already did, didn't you? Go on, admit it. It's ok, no one is reading this, it's just us), that we now have a second breakpoint, down around where things might start to likely get phone-ish. You'll find many different articles around how many breakpoints to have, what sizes you need to accommodate, what to do at each one. But when it comes down to it, just plan your breakpoints around where your layout stops working, and keep things fluid in between.
You'll also notice that The Hideous Footer seems to disappear when you get down to that narrow breakpoint. That's because when things get smartphone-small, a 2.5em high footer bar is a lot of screen real estate to eat up for no good reason, and there are already enough persistent horizontal bars in a mobile browser. On big screens, it might be nice to have it there all the time, but small screens don't need it (at least not for our purposes).
So we change the style on the footer so that it goes back to position: relative. When it is no longer fixed, it snaps back to its proper position in the HTML hierarchy (like the sidebars), which means it now shows up at the very bottom of our content, right where it belongs.
Not so good, huh? Well, that's because we didn't give our site the context-aware mojo of the <viewport> meta tag. This single, simple line of code in the head of your HTML document will save your sanity, and potentially let you control the experience for your users in a whole variety of ways. There are many resources for understanding <viewport>, but here is the code that I used:
What the above <viewport> tag does it tell the code to format the initial position and zoom of the page to show up so that everything is scaled and formatted properly for the device on which is is being viewed. There is a lot more to it than that - especially around how different size devices and orientations interpret zoom and scale, device pixels vs. CSS pixels - but for now, that's the gist of it. When applied, our site now shows up in a much more mobile friendly format:
See? From WTF? to FTW! in one short line of code.
The issue of What To Do With All Your Awesome Stuff is at the very core of RWD, and there are - of course - many different ways to handle it. A nice overview of the top five most common responsive layout schemes has been written up and illustrated by Luke W. - a very worthy read.
Based on my needs, I chose to go with what he calls the "column drop" pattern for my first breakpoint, which you can see in action when you resize down: the right-hand column drops down to the bottom below the main content.
I already knew where I needed my layout to break next, as we saw last time - when the nav comes too close to the logo, it's time for a breakpoint. In my case, that's 31em, and time to figure out what to do with that nav.
When things get small, otherwise lovely bits of interface need to change, and that very probably goes for your navigation too. The issue of navigation in the tiny world of mobile device space is a live one that each of us will need to handle in our own way, based on our users' needs.
Fortunately there has been a lot of very good, critical thinking about this topic, most notably in an article by the inimitable Brad Frost about responsive navigation patterns. I decided that I would go with "the toggle": navigation items are reconfigured from a single horizontal list to a styled vertical drop-down menu (as opposed to a system select menu, though that is another option) that appears only when the user requests it. Go ahead, try it out.
Our first bit of important Javascript shows up here. We want to make our nav open when the user clicks on the menu icon, and that click needs to change the classes on the menu to make it expand. So we use a little piece of JQuery:
What's going on here? Well, without a crash course on JQuery (which can be found free at CodeAcademy), here's the rundown. First, it checks to make sure that the DOM hierarchy is fully constructed (i.e. everything on the page is loaded so JQuery can work its magic), using the $(document).ready method.
When the DOM is ready, our function adds the ".js" class to the <body> so the CSS knows to only deal with it if we have javascript. If we don't have the .js class, this won't work, so the menu needs to default to open (right now there is messiness around this if JS is disabled - this will be addressed later). Then it creates a couple of variables to make working with the functions a little easier.
Next, it adds a function to the $menulink variable (which targets everything with the ".menu-link" class). This function says, in essence "Anything on the page that has the .menu-link class, listen up: when you get clicked, you need to toggle the '.active' and '.pushDown' classes." Since the <nav> and #mainContent don't have those classes by default, clicking the link adds them.
You can see this in action using the browser or developer tool of your choice ("Inspect Element" in Safari or Chrome, for example), and watching the html in the log as you open and close the menu. If you look at the page source, however, you will NOT see any of the classes added through JQuery; that gives you a static view of the code as loaded from the server.
This very effectively changes their styling, because in the CSS we have some additional styles defined for the menu to be in the open state. You can see all of the changes in the actual CSS, but the main differences are here:
When we hit the smaller breakpoint, the nav's max-height is set to 0, with any overflow hidden... it's there, but you can't see it. When the user clicks the menu button, the .active class gets added to the <nav>, and suddenly its max-height becomes $pushDownVal (my variable from the SCSS), which here translates to about 15em. It also adds the .pushDown class to #mainContent, increasing its margin-top by that same 15em.
The final bit of magic is our first CSS transition, which makes the menu appear to slide open gracefully rather than just appearing out of nowhere. In general, this is as simple as adding the following code to the elements you want to transition (in this case the <nav> and the #mainContent):
Nothing to it! But you DO need all those versions with different vendor prefixes in there, to handle different browsers. Vendor prefixes might seem annoying, but they are really a very good thing. Fortunately, if you are using Compass, it will do a lot of the heavy lifting for you with mixins, which can do all that dirty stuff in a single statement.
When all is said and done, if all goes well - and it won't in every case - you will get a nice smooth effect of the navigation sliding open and pushing the content out of the way.
Another small bit of javascript is used to enable the expansion of these accordion menus:
You click on a collapsed accordion panel (each of which has the class .accordionitem), and it toggles the class .openMe, which reveals the accordion content in a fashion similar to the nav bar.
You'll notice that these snap open rather than animating nicely. I lost some sleep over that.
The difference here is that I made a tactical mistake in creating the header as a PART of each accordion item. So I need to have the accordion partly revealed initially (a height of 2em) to let that header show through. Then, when clicked, the height expands to 100% to show all of the other content in the accordion panel.
This works ok, but led to my CSS Dope Slap Of The Day. I was trying to get my accordions to transition open smoothly, as the nav does. But no matter how I tried, or how much I Googled, I couldn't find a reason that it refused to transition smoothly. It took a lot of hair-tearing and trial-and-error before I finally realized that transitions will not work if you go from a static unit to a variable one, such as ems to % or px to auto.
This was a key realization, and I expect that I can fix it by making the header separate from the accordion panel, and then do a 0% to 100% height transition on each one when the header is clicked. But that's for another time.
I decided to just leave the header at the true top of the content and just let it scroll up and away with everything else, as it does at the other breakpoints. This works well and gives the user the maximum area on screen for content... but on small screens with a one-column layout things can scroll a long, long way.
To that end, I decided to give the user a conditional "back to top" link that would only show up after they've scrolled the header off the screen (and we'll use it for both of the smaller breakpoints, why not?). This is accomplished with some final javascript and one more style (this code is barely modified from Brian Cray's back-to-top link solution, out of the zillion+ out there; I could have rolled my own, but why reinvent the wheel for something like this?):
Once the user scrolls down from than 100 pixels below the top of the screen, up pops our back to top link. It may seem kind of large for a mobile screen, but don't forget the best practice teaching's of Apple's human interface guidelines: "44 x 44 points is the comfortable minimum size of a tappable UI element."The second, and possibly most important thing, is that The Hideous Footer is a little bit less hideous now - it is still position: fixed, but it now spans the entire width of the page, looking a little more integrated. Whew!
The next thing you'll notice, if you play around with the browser window (you already did, didn't you? Go on, admit it. It's ok, no one is reading this, it's just us), that we now have a second breakpoint, down around where things might start to likely get phone-ish. You'll find many different articles around how many breakpoints to have, what sizes you need to accommodate, what to do at each one. But when it comes down to it, just plan your breakpoints around where your layout stops working, and keep things fluid in between.
You'll also notice that The Hideous Footer seems to disappear when you get down to that narrow breakpoint. That's because when things get smartphone-small, a 2.5em high footer bar is a lot of screen real estate to eat up for no good reason, and there are already enough persistent horizontal bars in a mobile browser. On big screens, it might be nice to have it there all the time, but small screens don't need it (at least not for our purposes).
So we change the style on the footer so that it goes back to position: relative. When it is no longer fixed, it snaps back to its proper position in the HTML hierarchy (like the sidebars), which means it now shows up at the very bottom of our content, right where it belongs.
No more cheating: <viewport>
Last time, some of the more astute readers noticed that when they looked at the test1 site on a mobile device, it didn't look like you'd expect; it was just an unpleasantly tiny, zoomed-out version of the two-column regular site:| WTF? This is my responsive site? |
Not so good, huh? Well, that's because we didn't give our site the context-aware mojo of the <viewport> meta tag. This single, simple line of code in the head of your HTML document will save your sanity, and potentially let you control the experience for your users in a whole variety of ways. There are many resources for understanding <viewport>, but here is the code that I used:
<meta name="viewport" content="width=device-width, initial-scale=1">
| Ah, <viewport> tag FTW! |
See? From WTF? to FTW! in one short line of code.
WWEMDWAHS?
(or What Would Ethan Marcotte Do With All His Stuff?)The issue of What To Do With All Your Awesome Stuff is at the very core of RWD, and there are - of course - many different ways to handle it. A nice overview of the top five most common responsive layout schemes has been written up and illustrated by Luke W. - a very worthy read.
Based on my needs, I chose to go with what he calls the "column drop" pattern for my first breakpoint, which you can see in action when you resize down: the right-hand column drops down to the bottom below the main content.
| Rough sketch for breakpoint 2 |
The Nav of the Flightigator
Fortunately there has been a lot of very good, critical thinking about this topic, most notably in an article by the inimitable Brad Frost about responsive navigation patterns. I decided that I would go with "the toggle": navigation items are reconfigured from a single horizontal list to a styled vertical drop-down menu (as opposed to a system select menu, though that is another option) that appears only when the user requests it. Go ahead, try it out.
Our first bit of important Javascript shows up here. We want to make our nav open when the user clicks on the menu icon, and that click needs to change the classes on the menu to make it expand. So we use a little piece of JQuery:
<script>
$(document).ready(function() {
$('body').addClass('js');
var $menu = $('#menu'),
$menulink = $('.menu-link');
$menulink.click(function() {
$menulink.toggleClass('active');
$menu.toggleClass('active');
$('#mainContent').toggleClass('pushDown');
return false;
});
if ($('#wrapper').width() > 496) {
$('#mainContent').removeClass('pushDown');
$menulink.removeClass('active');
$menu.removeClass('active');
}
});
</script>
When the DOM is ready, our function adds the ".js" class to the <body> so the CSS knows to only deal with it if we have javascript. If we don't have the .js class, this won't work, so the menu needs to default to open (right now there is messiness around this if JS is disabled - this will be addressed later). Then it creates a couple of variables to make working with the functions a little easier.
Next, it adds a function to the $menulink variable (which targets everything with the ".menu-link" class). This function says, in essence "Anything on the page that has the .menu-link class, listen up: when you get clicked, you need to toggle the '.active' and '.pushDown' classes." Since the <nav> and #mainContent don't have those classes by default, clicking the link adds them.
You can see this in action using the browser or developer tool of your choice ("Inspect Element" in Safari or Chrome, for example), and watching the html in the log as you open and close the menu. If you look at the page source, however, you will NOT see any of the classes added through JQuery; that gives you a static view of the code as loaded from the server.
![]() |
| Checking out effects of toggling the menu button in the log view |
.js nav[role=navigation] {
overflow: hidden;
max-height: 0;
}
nav[role=navigation].active {
max-height: $pushDownVal;
}
#mainContent.pushDown {
margin-top: $pushDownVal;
}
The final bit of magic is our first CSS transition, which makes the menu appear to slide open gracefully rather than just appearing out of nowhere. In general, this is as simple as adding the following code to the elements you want to transition (in this case the <nav> and the #mainContent):
-webkit-transition: all 0.3s ease-out;
-moz-transition: all 0.3s ease-out;
-ms-transition: all 0.3s ease-out;
-o-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
When all is said and done, if all goes well - and it won't in every case - you will get a nice smooth effect of the navigation sliding open and pushing the content out of the way.
Perfect Pitch
What's the definition of perfect pitch? When you throw a banjo into a dumpster and it hits an accordion (apologies to Chris Coyier - I can give you a dozen bass player jokes if you need revenge). Well in our new layout, you'd better start hurling the banjos, because there are THREE accordions!Another small bit of javascript is used to enable the expansion of these accordion menus:
$('.accordionitem').click(function() {
$(this).toggleClass('openMe');
return false;
});
You'll notice that these snap open rather than animating nicely. I lost some sleep over that.
The difference here is that I made a tactical mistake in creating the header as a PART of each accordion item. So I need to have the accordion partly revealed initially (a height of 2em) to let that header show through. Then, when clicked, the height expands to 100% to show all of the other content in the accordion panel.
This works ok, but led to my CSS Dope Slap Of The Day. I was trying to get my accordions to transition open smoothly, as the nav does. But no matter how I tried, or how much I Googled, I couldn't find a reason that it refused to transition smoothly. It took a lot of hair-tearing and trial-and-error before I finally realized that transitions will not work if you go from a static unit to a variable one, such as ems to % or px to auto.
This was a key realization, and I expect that I can fix it by making the header separate from the accordion panel, and then do a 0% to 100% height transition on each one when the header is clicked. But that's for another time.
Home... is where I want to be
The final piece I wanted to try out was similarly to try and make things nicer for the small-screen user. I tried having the nav bar fixed at the top of the screen for the mobile user, so that no matter where they were on the page they could get around the site. That was convenient in one way, but further added to the issue of too many bars on the screen and not enough space for just content.I decided to just leave the header at the true top of the content and just let it scroll up and away with everything else, as it does at the other breakpoints. This works well and gives the user the maximum area on screen for content... but on small screens with a one-column layout things can scroll a long, long way.
To that end, I decided to give the user a conditional "back to top" link that would only show up after they've scrolled the header off the screen (and we'll use it for both of the smaller breakpoints, why not?). This is accomplished with some final javascript and one more style (this code is barely modified from Brian Cray's back-to-top link solution, out of the zillion+ out there; I could have rolled my own, but why reinvent the wheel for something like this?):
<script>
$(function () {
var scroll_timer;
var displayed = false;
var $backToTop = $('#backToTop a');
var $window = $(window);
var top = $(document.body).children(0).position().top;
$backToTop.fadeOut(0);
/* react to scroll event on window */
$window.scroll(function () {
window.clearTimeout(scroll_timer);
scroll_timer = window.setTimeout(function () {
if($window.scrollTop() <= top+100)
{
displayed = false;
$backToTop.fadeOut(500);
}
else if(displayed == false)
{
displayed = true;
$backToTop.stop(true, true).show().click(function () { $backToTop.fadeOut(500); });
}
});
});
});
<script>



