Cristian in CSS, Javascript
January 23, 2009
During the years I’ve been through so many solutions to achieve a sticky footer solution, from the one explained at Exploring Footers (A List Apart) to different variations that at Gimmicklab we have re-using and re-thinking, some based on pure CSS and some taking advantage of Javascript.
Yesterday I was taking a look at CSS Sticky Footer, a pure CSS technique that provides this functionality with full crossbrowser compatibility.
We have been using a similar method in the past with great results, but the thing that I’ve been always complaining is that it made me change our mark up structure.
Since we work with a XHTML and CSS styleguide for our every project that establish the following general mark up among other rules:
<div id="container"><div id="header"><div><div id="main"><div><div id="footer"><div><div>
So changing the structure wasn’t fitting all our necessities, considering that to make it run only with CSS we should close #container element right after the# main , leaving the #footer outside the general structure.
<div id="container"><div id="header"><div><div id="main"><div><div><div id="footer"><div>
Although this is a clever techniqe and due to the high volume of projects that we are working, our necessity of a solid structure across several projects it’s actually stronger than any design necessity, so we finally developed a script to achieve the same effect with our actual general mark up. And it’s reusable for every different structure.
The XHTML mark up is the following:
<div id="container"><div id="header"><div><div id="main"><div><div id="footer"><div><div>
And the CSS, you should apply after any kind of CSS reset. I suggest Eric Meyer’s approach.
body, html, #container {
height: 100%;
}
#main {
height: auto;
}
You can fix a height for the header and the footer if you like, even in the container if you want to try different layout structures.
And now some Javascript code.
function matchHeight() {
var finalHeight = document.getElementById('container').offsetHeight - document.getElementById('header').offsetHeight - document.getElementById('footer').offsetHeight;
var mainElement = document.getElementById('main');
mainElement.style.height = finalHeight + 'px';
}
window.onload = matchHeight;
window.onresize = matchHeight;
As you can see you have to set body, html and #container to 100%, and give to #main an automatic witdh.
The javascript determines the exact height of the main element pushing the footer element until the end of the page.
The main height size is the result to calculate the container height (100% of the viewport) minus the header and footer height.
And here it is a Jquery version of the javascript code:
$(function(){
matchHeight();
function matchHeight() {
var mainHeight = $("#container").outerHeight() - $("#header").outerHeight() - $("#footer").outerHeight();
$('#main').height(mainHeight);
}
$(window).resize(matchHeight);
});
We tested the technique in diferent browsers and OS: Firefox (Win/Mac/Linux), Safari (Win/Mac/Iphone), IE6, IE7, IE8 (Windows), Opera (Mac).
The complete code and example page with Javascript and JQuery.
Comments(4)
That looks nice and the list of tested configurations is impressive.
I still have two general JS tweaks to offer that reduce the amount of code which is, in my opinion always a good thing, as long as it doesn’t degrade readability and by that maintainability.
My first hint is for JS in general. In JS there are two kinds of function references. The first one is an anonymous function, exactly what you used above. The second one is the name of any already defined function, which is especially helpful in case you want to register an event handler that just calls another parameterless function. Instead of writing
window.onresize = function() {
matchHeight();
}
you could just write window.onresize = matchHeight;This works with jQuery as well.
$(window).resize(function(){
matchHeight();
});
can be reduced to $(window).resize(matchHeight);
My second hint is jQuery related and makes use of my first hint. Instead of saying $(document).ready(some_function); you can always pass that function reference directly to the $ function, like $(some_function);
Hi Daniel!
Thanks for your tips, I just added them to the code. Now that I’m getting introduced to Javascript and Jquery it’s nice to see some shorthand variations and best practices.
You might also want to check to make sure the content div is less than the windows height to apply the effect. Here’s my modification.
function matchHeight() {
var winHeight = $(window).height();
var wrapHeight = $(“#wrapper”).height();
var mainHeight = $(window).height() – $(“#header”).height() – $(“#footer”).height();
var mainHeight2 = mainHeight + 91;
if (wrapHeight < winHeight) {
$(‘#wrapper’).height(mainHeight2);
}
}
I based it off of this article by ALA which checks the condition.
Nice! It makes more sense now. I will add it to the example. Thanxs for sharing!
Insert Comment