Read my book

I wrote books about Webpack and React. Check them out!

Thursday, September 12, 2013

Build Your Own Fluid Fixed Header Using CSS

It's time for yet another build your own type of posts! This time I will talk about headers. It seems to me that there is some kind of a design trend going on. People are using fixed headers more and more. There's one particular variant that has caught my eye. It is a fluid fixed header. I am not sure if there's a definite term for it but I think that describes it somewhat.

The idea is that the header is "fluid" up till certain point. After that it becomes fixed and stays at the top while having less height than originally. This is useful if you have some nice imagery to show and want to highlight a motto. As the user scrolls the page this information will be hidden as the user was converted by your hopefully awesome design.

Implementing this technique is quite simple. My implementation doesn't support older browsers as it uses semantic markup provided by HTML5 and relies on some newer CSS features. It appears to work just fine in the current generation, though. I think it is possible to overcome this by adding some kludges (less semantics markup, shims etc. hacks) but to keep this nice and tidy I will present you the modern version.

The markup required will be quite simple. The following list shows the basic elements:
  • header
    • h1 - Main header and possible motto
    • nav - Navigation
      • a - Your navigation links
  • article
    • Your actual content goes here
Of course you could have aside etc. elements based on your need. This is just a simple structure to get started with.

In addition we will require a bit of JavaScript and CSS. I will start out by describing the JavaScript as that will show the basic idea well:
$(main);

function main() {
    var $header = $('header');
    var offset = $header.height() - $('nav').outerHeight();

    $(window).on('scroll', function() {
        if($(this).scrollTop() >= offset) $header.addClass('fixed');
        else $header.removeClass('fixed');
    });
}
The solution is based on jQuery but it should be easy to port it to other environments. We need to simply keep track of scroll event and then decide whether or not our header is fixed. We will deal with the actual layout concerns using CSS. How you do this depends a lot on your exact requirements. I've sketched out one possible solution below:
* {
  margin: 0;
  padding: 0;

  font-family: sans-serif;
}

a {
  color: #4e5947;

  text-decoration: none;
}

header {
  position: relative;
    
  width: 100%;
  height: 25em;
  
  background: url("http://placekitten.com/g/1128/400");
  -o-background-size: cover;
  -webkit-background-size: cover;
  -moz-background-size: cover;
  background-size: cover;
}
header h1 {
  padding-top: 2em;
  padding-left: 2em;
}
header a {
  height: 3em;
  
  min-width: 10%;
}
header.fixed {
  position: fixed;

  background: none;
  height: 1em;
}
header.fixed h1 { display: none; }
header.fixed a { height: auto; }
header.fixed nav { opacity: 1.0; }

nav {
  position: absolute;

  bottom: 0;

  width: 100%;

  background: #333;
  opacity: 0.8;

  overflow: auto;
}
nav a {
  float: left;
  
  padding: 1em;

  line-height: 0;
    
  color: #ddd;
}
nav a:hover { background: #555; }

article { margin: 1em; }
article p {
  margin-top: 0.5em;
  margin-bottom: 0.5em;
  
  line-height: 1.5;
}
It's a lot of code and you can likely eliminate some. Still, it's a starting point!

As you might be curious to see what the result looks like, consider the demo below:



Thanks to Udi Falkson of iknow.io for giving a couple of helpful pointers! iknow.io is an aggregator of sorts for big data. You can build your own comparisons using it. The service is its early stages but it looks like bloggers and journalists might find it very handy.

I met Udi through wizpert. wizpert allows people to ask direct help from various experts. In fact you may contact me through the service on technical matters. Another acquaintance I made through the service lead to some interesting results but I'll elaborate on that later. Till the next post!