Responsive Web Design: Mobile First & Progressive Enhancement

Responsive Web Design: Mobile First & Progressive Enhancement

Welcome to the second post in my Responsive Web Design series. If you haven't already, check out the first post on the essentials of responsive web design.

When responsive web design first came on the scene, most of us were still caught up designing for desktop and mobile separately. At first it might have seemed that we no longer needed our mobile websites anymore as we could now just scale down our desktop sites. A few max-width media queries here and there and we were good to go. It quickly became apparent however that this approach alone was not enough.

The suggestion of a mobile first design approach actually precedes that of responsive web design. Luke Wroblewski first coined the term back in his November 2009 blog post, unsurprisingly named Mobile First. This was later followed up by a book in the A Book Apart series. Luke had observed the huge growth in mobile internet access pushed on by the rapidly growing adoption of smartphones. This indicated that not only should we be prepared for this growth, but we should embrace it wholeheartedly and turn our usual design approach on its head. The fact that mobile websites were designed for devices with limited screen real estate and unreliable bandwidth meant they had to be focused, uncluttered and light. What desktop website wouldn't benefit from some of that lean goodness?

"So when a team designs mobile first, the end result is an experience focused on the key tasks users want to accomplish without the extraneous detours and general interface debris that litter today's desktop-accessed Web sites. That's good user experience and good for business."

In addition, mobile browsers opened up more possibilities than your standard desktop browser with location via GPS, cameras, NFC (Near Field Communications), etc. Whilst support for these features has been patchy, it has improved with every new release.

What does this have to do with responsive web design?

Everything Luke brought to our attention about the benefits of thinking 'Mobile First' fit like a glove with the goal of responsive web design, one website to rule them all. It had been difficult to decide where all these desktop page elements (clutter) were going to fit on our small smartphone screens. And what about our navigation, hover effects, images, etc? Desktop websites that had been given the responsive overhaul were still too heavy and not always thought out very well. Navigation was frequently bunched so close together that you couldn't always hit the desired target. Some also relied on hover effects to indicate their presence and/or state which left visitors bemused.

A clean slate

So let's start out fresh! With a limited amount of space available, we have to get ruthless and cut out the crud. This part of the approach goes hand in hand with another known as 'Content First' which stresses not only uncluttered, leaner content, but also the priority of content over other elements like navigation. Who wants to scroll down through all of your navigation links to find what they actually came to see ... your content!

Let's assume you have now binned any unnecessary page elements and are ready to tackle the primary site navigation. Whether left or right handed, most people use their thumb when operating a phone with one hand. It therefore stands to reason that your navigation should be placed at the bottom of the screen. Having said that, smartphones are getting bigger all the time so single handed operation may not be possible for those with smaller hands. Let's play along for now though and place our navigation at the end of our content (Note this also means it isn't getting in the way of our all important content). We are also going to make sure that each navigation item allows enough space for our chubby fingers to prevent any unexpected behaviour.

        ...
		<section class="site-content">
            <div class="wrapper clearfix">
                <section class="main">
				...
				Your content here
				...
                </section>
                <nav id="site-nav">
                    <a name="nav"></a>
                    <ul class="nav-list">
                        <li><a href="/">Home</a></li>
                        <li><a href="/about">About</a></li>
                        <li><a href="/blog">Blog</a></li>
                    </ul>
                </nav>
            </div>
        </section>
        <footer class="site-footer">
		...
#site-nav {
  display: block;
  width: 100%;
}
.nav-list {
  display: block;
  list-style-type: none;
  padding: 0;
  margin: 0;
  width: 100%;
}
.nav-list li {
  display: block;
  width: 100%;
}
.nav-list li a {
  display: block;
  padding: 0 1em;
  text-align: right;
  font-size: 1.4em;
  line-height: 2.4em;
  height: 2.4em;
  white-space: nowrap;
}

This is a good start but hang on, doesn't this mean we now have to scroll all the way through our content to get to the nav? Well, yes it does. So let's make that a little easier by putting a subtle but obvious link at the top of the page that will whisk us down to our navigation. The most common form for this link is the faithful 'hamburger' link. I use an icon font this but you can use SVG or just an image if you want. The first two are preferable as they scale well.

        <header class="site-header">
            <div class="wrapper">
                <a href="/" id="header-logo">Your SVG/Icon/Image Logo Here</a>
                <a href="#nav" id="site-nav-toggle" class="icon-alone">Your SVG/Icon/Image Hamburger Here</a>
            </div>
        </header>
#site-nav-toggle {
  float: right;
  margin: 10px 10px 0px 0px;
  border: 0;
  outline: none;
  font-size: 22px;
  line-height: 22px;
}
Navigation moved to the end of the content

Great stuff, looking good. Content is up front and center where it should be and our main navigation is out of the way but easily accessible. It turns out however that not everyone is a fan of this approach and can get confused when they suddenly find themselves at the bottom of the page after clicking on our hamburger button. This is especially obvious if you don't have many navigation items as they don't fill the screen and so the bottom of your content is visible above. We need some help.

A tale of two strategies

Graceful Degradation VS Progressive Enhancement

As far back as 2003, two men (Steve Champeon and Nick Finck) were challenging what had for almost 10 years prior been an accepted strategy for delivering content - Graceful Degradation. The original idea was that when certain 'newer' features were not recognised by older browsers, the important content would still be visible, whilst the 'extras' would gracefully disappear without making a scene. This could be achieved for example by browser (and version) specific style sheets through various hacks. Unfortunately this wasn't as ideal as it sounds. Firstly designers rarely looked back beyond the previous version of a given browser which left all the users of older versions with a suboptimal experience. Also these webpages were cluttered with elements that were utterly useless to these older browsers and just added unnecessary weight.

Their proposition - Progressive Enhancement - suggested turning the old approach on its head (sound familiar?) and starting out with the basic content. We could then, where the required support was available, add the bells and whistles to our base. That way everyone could be happy, from the most basic content experience up to the fully featured, 'throw everything at it' version.

In its most basic form, progressive enhancement refers to a base of semantically marked up content, which can then be enhanced by separate CSS styling where supported. The content can then be further enhanced by JavaScript (again where supported), maybe by including additional content via an AJAX call.

Today there are many libraries and techniques that help us to check for support of all sorts of features including the CSS3 and HTML5 palettes. In some cases we can even add those features to non supporting browsers with some black magic known as polyfills.

Plugging the gap

Whilst progressive enhancement tells us to include features only where support is available, another approach is to add that missing support, normally via JavaScript. Remy Sharp was the first to coin the term 'Polyfill' when trying to describe something that adds an API to a browser that doesn't already have native support.

Here are a few polyfills that I use regularly:

  • html5shiv: Adds support for HTML5 elements. Note this isn't required if you are using Modernizr as it is included.
  • Respond.js: Adds min/max-width CSS3 Media Query support (mainly for IE6-8 but works on some others) by re-requesting and parsing the CSS files then dynamically adding/removing the matching CSS to the DOM.
  • Media.match: Adds matchMedia API support to allow JavaScript testing of CSS media queries.

Enhanced navigation

Earlier we created our mobile first navigation that sits at the bottom of the screen for browsers that don't support JavaScript. For those that do, we can move the navigation back up top and enhance it with a nice show/hide effect (with a little help from jQuery) behind our hamburger button.

$(document).ready(function() {
	$('#site-nav').insertAfter('.site-header').css('display','none');
	$('#site-nav-toggle').attr('href','#').click(function(e) {
		$('#site-nav').slideToggle("fast");
		e.preventDefault();
	});
});
Navigation moved back to the top

Let's take things a step further and change our navigation at different break points so we get a more traditional navigation menu in larger viewports. I have tried to achieve this without the help of JavaScript.

@media screen and (min-width: 50em) {
  // Position the navigation block top right
  #site-nav {
    display: block;
    position: absolute;
    top: -65px;
    right: 0px;
    bottom: auto;
    left: auto;
    width: auto;
  }
  // Display navigation items inline
  .nav-list {
    float: right;
    width: auto;
    background: none;
    border-bottom: none;
  }
  .nav-list > li {
    width: auto;
    float: left;
    display: inline;
    border: none;
  }
  .nav-list > li > a {
    background: none;
    float: left;
    text-align: center;
    font-size: 1.4em;
    line-height: 1.4em;
    padding: 0;
    margin-left: 1.6em;
    margin-top: -10px;
  }
  // Hide the hamburger button
  #site-nav-toggle {
    visibility: hidden;
  }
}

We have a small problem now that if JavaScript is enabled, the earlier code would have already moved our navigation block to a different location and we would get unexpected results from our CSS media queries. Ideally we want to move our navigation block back when the above media query matches. Using an awesome little library called enquire.js, we can replicate our CSS media queries and trigger our enhancements at specific break points. Let's replace the earlier JavaScript with the following:

// Move navigation block for smaller viewports and move back when match lost (larger viewports)
enquire.register("screen and (max-width: 49.9em)", {
	match : function() {
		$('#site-nav').insertAfter('.site-header').css('display','none');
		$('#site-nav-toggle').attr('href','#').click(function(e) {
			$('#site-nav').slideToggle("fast");
			e.preventDefault();
		});
	},
	unmatch : function() {
		$('#site-nav').insertAfter('.main').css('display','block');
		$('#site-nav-toggle').off('click');
	}
});
// Display navigation block for larger viewports and hide when match lost (smaller viewports)
enquire.register("screen and (min-width: 50em)", {
	match : function() {
		$('#site-nav').css('display','block');
		menu.init();
	},
	unmatch : function() {
		menu.destroy();
		$('#site-nav').css('display','none');
	}
});
Navigation on larger viewports

I couldn't discuss progressive enhancement and not mention one of the best tools in the box. Modernizr allows you to test for specific CSS3 and HTML5 feature support. It then adds CSS class names to the html element to show which tested features are supported. You can then precede your own class names with the Modernizr ones to ensure your styles are only applied when that feature is supported. Maybe I will cover this in another article, but please do check it out.

So there you have it, a base navigation that is optimised for mobile first, then progressively enhanced with CSS and JavaScript. The same principles can and should of course be applied to other aspects of your design. And you can take the whole progressive enhancement idea much further with dynamically loaded page elements via Ajax etc. Let's allow everyone to enjoy their encounter with your website regardless of browser or device and access your content in an appropriate way.