Friday, October 12, 2012

How To Be Responsively Responsible, Part 3: Making Progress!

Matt masters the vagaries of the web
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.

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.

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:


My test site without the viewport meta tag
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">
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:


My test site WITH the viewport meta tag - much better
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.


Sketch of breakpoints in the test site
Rough sketch for breakpoint 2
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.


The Nav of the Flightigator

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:
<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>
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.
Animation showing classes toggling on and off in the browser log
Checking out effects of toggling the menu button in the log view
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:
.js nav[role=navigation] {
     overflow: hidden;
     max-height: 0;
}
 
nav[role=navigation].active {
     max-height: $pushDownVal;
}
 
#mainContent.pushDown {
     margin-top: $pushDownVal;
}
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):
-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;
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.


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 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.


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>
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."


Time for a breather

Well we've covered a lot of ground, but there's still a lot left to do. Next time we'll start correcting some of the trespasses of this iteration, and perhaps start getting a little fancier. Until then, code on!


Wednesday, October 3, 2012

How To Be Responsively Responsible, Part 2: Baby Steps


The Fly (you know, caught in the web...? Aw, forget it)

</whine>

OK, so enough whining about the options out there; it's time to actually try my hand at some responsive web design (RWD)!

But where to start?

Planning, of course!

First of all, I decided that rather than diving straight into trying to redesign my own site - you know, with all that actual content and stuff - it would be better if I did some proof of concept pages to get my hands dirty and get solidly back into code. That's where we're starting.

To this end, I didn't go into great depth with content cataloging, sketching, wire framing, etc., simply because I'm not planning to use real content for this demo. Of course, I am fully aware that the demo might just roll right into the real deal, so I want to try and do things pretty well from the start… but let's start small.

I did do something of a mini "content catalog" and "wireframes" to have some idea what I'd be dealing with. Basically, I knew I'd need the following:
  • A header, which would consist of a nav bar with 5-6 items and a logo
  • A main content area which would consist of various sections, articles, etc. to be determined later
  • A sidebar area that could have several elements
  • Another, rogue, floating sidebar element that I could play with
  • A footer
That's about all I need to get started, as far as elements. But thinking about actual content and the priority of different content elements is very important in responsive design. Since the idea is for your user to be able to consume your content in any context, you need to know what elements will be most important to them in each context, and how to make your page reconfigure to display that content best on different devices.

The discussion around whether or not to specifically tailor your site and content to a specific device context is a lively one, but if you observe the most basic best practice - know your user and business goals - you can probably figure out how to approach this.

For now, my user is me, and I don't want to hide any content from anyone, so everything needs to reconfigure itself nicely. This first project will kind of be a content prototype, but without any real content.

Based on the "content" that I identified above, I did a quick "wireframe" to see how these pieces would fall in a regular desktop format, and in a narrower one (we'll just do one breakpoint for now):

Ooooh, fancy!

I know from many years of video experience that there's no point in making your own storyboard templates when there are dozens out there on the web - enough that it's probably quicker to Google it than to even fire up Illustrator. I did a quick search and, sure enough, found some great, simple RWD layout planning templates by Jeremy Alford, which are the thin, straight lines you see around my scrawls up there.

So now it's time to code. 

I am assuming that, if you are here, you already know some HTML and CSS and are interested in getting down and dirty with some RWD yourself. If you are new to web coding, I would strongly suggest you get up to speed before going much further. There are countless ways to do this; Treehouse and Lynda.com are two excellent paid resources, but there are some great free ones out there as well; check out the html.net and Tuts+ sites to get started.

I decided that for these first steps not to use any frameworks, boilerplates, grids or anything - just see if I can throw together a nice, simple demo that would give me a good, semantic framework upon which to build, and to get used to using SASS and Compass.

Yes, I settled on SASS… after a lot of exploration and debate, and a few articles (here's one, and another, oh and one more) on the subject, I decided SASS would be better because a) it's got all the nifty Compass functionality if I want to use it, and b) a couple of the guys in my department were already using it, so best to keep techno-solidarity there. SASS it is.

Or more accurately, SCSS, since I am not using much of the special SASS syntax right now. I'm mostly taking advantage of the nesting and variables made possible with SCSS, maybe a few mixins from Compass, and letting Codekit take care of all the compiling and organization in the background for me. To see a bit more about how I have used SCSS variables in my code, take a look at the CSS code - there are some comments in there for you.

Did I already gush about Codekit? Time for another gusher. If you are a Mac developer and you aren't using Codekit, RUN, don't walk, and get this thing (sorry, Win-folk, there's no version for you yet, and apparently no alternatives... but it's coming). If you are using any preprocessors for HTML, JS or CSS, or if you want to save a crap-load of time setting up fancy schmancy CSS effects and transitions, this little application will save you a lot of effort and interaction with the Terminal (don't be afraid of the terminal, but still get Codekit). Anyway, it is SO worth the $25. And tech support is quick and first-hand, let me tell you.

Behind the mask

First of all, though, what we need is a nice, simple semantic framework. To that end, join me on a zany, madcap adventure to the wonderful world of completely unstyled HTML:


Yes, that's what our page looks like with no styles at all, just the most cursory <h> and <p> tags. Ugly as sin, but clear enough - if you can get to this page, you can figure out what's going on and where to go. This principle is beautifully demonstrated by the now age-old CSS Zen Garden. This site shows wonderful examples of the separation of structure and style; do yourself a favor and play around there for a while.

Now, while I am not going to use any templates, I am most definitely going to use a CSS reset to kick things off. A CSS reset is almost always a good idea - at their simplest, they reset some browser defaults to 0 to give your site a standardized playing field to work on across browsers. Some of them also fix known issues with certain browsers, optimize things for HTML5 or fluid grids, etc. But there are two accepted guidelines: You should use a CSS reset, and whichever you use, only use it as a starting point; they are meant to be customized by each developer for his or her unique situation.


Now based on past experiences, I figured I'd start with the Eric Meyer reset (now in v2.0) and do some tweaking. I also used some bits from Normalize, as well as a brilliant box-model fix by the equally brilliant Chris Coyier (known for CSS-Tricks.net and the incredibly addictive Codepen) which allows us to use margins and padding without messing up our fluid layout. You can read a lot more about that piece here. For a closer look at a variety of popular reset starting points, you can visit CSSReset.com.

CSScapades - now we're stylin'!

Before I go too much further into the discussion of the code, how about a little peekskie at the properly styled test page?


Now hold on just a cotton-pickin' minute here!

What's that you say? "I looked at your test page on my iPhone and it isn't responsive! That darn site just showed up as a two-column site zoomed way out. You're cheating!" Ok, guilty as charged, but there's a reason for this (you knew there would be, didn't you?), and it's called the <viewport> tag... but we'll go into that next time. Promise.

Web Fu
So, the first thing you'll notice when you look at the styled site is that the visual design is about as tasty as an overripe cardboard box. That's on purpose, people - I want this to be as close to an interactive wireframe as I can get so as not to confuse function with form. Fancypants stuff will come in time - patience, young Grasshopper.

The one concession I made towards improving the visuals was to use a couple of web fonts rather than leave things to chance. To that end, I used Google Webfonts, and am using Signika Negative for the headers and Cardo for the copy. The font is added with a simple <link> in the <head>, and then you can use it in your CSS - bang. Web fonts can be embedded in other ways, of course, and as always there are benefits and drawbacks.

But now go ahead... play around with the browser window for the styled test page. You'll notice that the major areas are fluid, which is one of the cornerposts of RWD. Wherever possible I am using % and ems to define sizes rather than px.

Originally, back in the stone age (2008?) when browsers didn't all scale things very consistently, elements defined with specific pixel values would not always re-size properly, breaking all kinds of layout stuff. Which is, of course, bad. Using variable values such as ems and percentages helped fix that.

These days most browsers are smart enough to zoom things right, so the best reason to keep it relative is more for your own sanity: if you keep things as fluid and relative as possible, you don't need to calculate and code every column width and font size for each breakpoint. But don't take my word for it.

Breakin' 2: Electric Boogaloo

Tastier yet - speaking of breakpoints, we now have our first media query! When the page re-sizes horizontally below 48em (in my SCSS this is a variable called $smallDeskWidth, which you can see below), it goes from being a 2-column layout to a 1-column layout. The sidebars snap below the main content area and all elements become full-width. This is accomplished with one very simple media query (stripped down here to the critical bits):
@media only screen and (max-width: $smallDeskWidth) {
#wrapper {
width: $smallDeskWidth;
max-width:94%;
min-width: 29em;
}
#sideBar  {
float: none;
clear: both;
width: 100%;
min-height: 100px;
}
#mainContent {
width: 100%;
}
}
This is placed at the very bottom of my SCSS/CSS document so that things cascade properly; stuff you define later in the document overrides stuff that you define earlier in the document, assuming the conditions are right. So if that browser width gets narrower than $smallDeskWidth, the styles override the ones set higher up. Simple!

When triggered, both the #sideBar and the #mainContent areas become 100% wide (within the max-width of 94% set by the #wrapper) and get stacked on top of each other. The reason the sidebars snap below the main content is that this is where they live in the actual HTML flow (refer either to the source code or the first, unstyled test). When they were floated right, they stacked atop each other on the right hand side and the #mainContent "flowed" around them. When that float is cleared, they suddenly lose their special privileges and hop back in line with the rest of the HTML.

The issue of content choreography - or where various chunks of content go when things re-size - is non-trivial, and there are many ways to handle it, none of them quite perfect. We'll look at this more going forward, but for now suffice it to say that a content strategy (or at least some kind of hierarchy) is very important when you might be dealing with very limited viewing areas.

You've probably noticed by now that the new single column will not re-size BELOW 29em (as you can see from the code, that is on purpose, defined by a min-width). This is because I know the layout as it stands will break if I size it down much more, and I want to add another breakpoint in there to handle it (why do you think they call 'em breakpoints?). Having your nav crash into your logo is very bad form. But that's for next time.

You'll also notice the footer, which is fixed at the bottom of the page and remains perpetually 6em from the edges of the browser window no matter how much you flail that mouse around. As it stands, it is at the bottom of the page, just where you'd expect to find it given its position in the HTML document. The cool thing is that, because I have defined its position as fixed in relation to the bottom and sides of the browser, you could put the <footer> code anywhere in the HTML and it would still show up right there at the bottom.

For now, this just proves a point - defining something as position:fixed in a layout is a powerful tool that we can use for all kinds of interesting things. But as the footer is now, I kind of hate it, the way the left edge stays static and the right moves around, and it can be either wider or narrower than the main layout depending on your window width... yuck. To be fixed later.

Are we having fun yet?

So, my goals for the next iteration are pretty clear: Set a second breakpoint below 29em; figure out if that accordion thingy is going to be an accordion thingy (and make it work); add enough content to make it need to scroll, which will afford some new opportunities; fix the hideous footer; find a way to use a little JS in there; and maybe improve the visuals a bit. Oh, and we'll address that <viewport> issue as well and start making things look good in mobile contexts.

Until next time, please let me know if you have any questions about anything (I can be very responsive!) and stay flexible.