Exploring Footers

One of the nice things about old-school table layout methods is that they enable you to create liquid page designs very easily. If you want to center content vertically or stick a footer to the bottom of the browser window, all you have to do is include one main table with a height of 100% and position elements inside of it.

Article Continues Below

With web standards, you can’t do this anymore. The table height property is deprecated in XHTML, and web standards recommend that you avoid using tables for page layout. To divide structural markup from presentation, CSS is the way to go — but if you want to use CSS for vertical positioning, you face a lack of support from some mainstream browsers.

This article explores the ways you can position footers using web standards, although the same techniques may be used to vertically position other elements. Many designs contain a footer that is positioned directly under the content area, unless the content and the footer together don’t fill the window entirely. In this case, the footer will be positioned at the bottom of the browser window.

Absolute positioning in a relative box#section2

So how do you position a footer with CSS? Picture a container with a fixed width. The container consists of a variable amount of content followed by a footer with a fixed height. When you add content, the height of the container grows; when you subtract content, it shrinks.

If you create a relatively positioned container and nest a content block, by default it will follow the normal flow inside the container, expanding or diminishing the height of its parent with its content. One of the strengths of relative positioning is that you can nest absolute-positioned elements inside of them. This makes it possible to nest a footer block and position it absolutely to “stick” at the bottom of the container. Your markup code looks like this:

<div id="container">
    <div id="content">...</div>
    <div id="footer">...</div>
</div>

And your style rules look like:

#container {
    position: relative;
 }#footer {
    position: absolute;
    bottom: 0;
 }

However, absolutely positioned elements are taken out of the normal flow and are placed over normal flowed elements. Because you don’t want your footer to overlap your content, you can add some padding to the bottom of the content block to compensate the footer’s height. You may view the result in example 1.

This step doesn’t work correctly in Internet Explorer 5.x/Windows. For these browsers an absolutely positioned child loses its position when the height of the parent element is not set. We will focus on the container’s height in the next step.

Connecting the container to the viewport#section3

So far, the height of the container is determined by the height of the content block, which is cool if there is enough content to fill the height of the browser window (also called the viewport). If this is not the case you want the footer to stick to the bottom of the browser window.

In CSS, this is an easy effect to create. If you give the container a minimum height of 100% with the min-height attribute, the minimum height of the container is equal to the height of its parent element: the body element. You specify that the height of the body element must equal the height of the viewport by setting the height of both the body and the html element to 100%:

html, body {
    height: 100%;
}
#container {
    position: relative;
    min-height: 100%;
}

You may view the result in example 2. This is all the code that should be needed to position a footer with CSS. Unfortunately this technique doesn’t work for Internet Explorer and Safari because of their lack of support for the min-height attribute.

But wait a minute, the technique works in Internet Explorer 6, even though that browser doesn’t support the min-height attribute (at least not according to the W3C specs).

It appears that if you set the height of the body element to 100%, in Internet Explorer 6 (in Standards mode) the container inherits its parent’s height (in our case the viewport’s height). Internet Explorer’s wrong implementation of the default visible value of the overflow attribute (on Windows only) causes our container to stretch up until its content fits in it, instead of maintaining a fixed 100% viewport height. These two together effectively simulate a min-height attribute.

Working around some limitations#section4

Internet Explorer 5.x/Windows always renders a web page in quirks mode. If you set a block element’s height to 100%, in quirks mode, the element uses the height of the viewport. Now if you could only declare a height of 100% for the container, this would fix the problem from the first example and make the technique work in IE5/Windows too. Note that if you set the height of the container to 100%, in standards mode the footer will always stay at the bottom of the browser window.

Using the box model hack, you can pass style rules to Internet Explorer 5.x/Windows only. You define the height of the container as follows:

#container {
    position: relative;
    min-height: 100%;
    height: 100%;
    voice-family: ""}"";
    voice-family: inherit;
    height: auto;
 }
 
html>body #container {
    height: auto;
 }

You may view the result in example 3. Example 3 doesn’t work in Internet Explorer 5.x/Mac and Safari, but it degrades gracefully; the footer will always be placed at the bottom of the content block.

Microsoft has stopped developing Internet Explorer on the Mac. I hope Apple’s Safari will support the min-height attribute soon. Meanwhile, what if you want to support Safari or Internet Explorer 5/Mac (or, most likely, both)? Are there any other alternatives? Funny you should ask.

What about the W3C DOM cavalry?#section5

Unfortunately, the W3C did not create any specifications on how to calculate the height of both browser window or document elements. They probably should have; standards exist so browser makers don’t have to create these specifications themselves. In this case browser makers were forced to create their own proprietary attributes.

So if you want to use scripting to position elements relative to the browser window, you are condemned to use non-standards-compliant proprietary techniques. The question is: Is it a bad practice to use these techniques in an area where there is a lack of standards?

In my opinion, this depends on how internally consistent these techniques are. If they are able to fill in the gaps of web standards and are used in a consistent way, I think they should be treated the same way as W3C specifications.

If you have the choice between a pure CSS solution and one that combines CSS and scripting, it is wise to use CSS only. In principle, CSS should take care of style and JavaScript of behavior. However especially in the cases where standards are supported poorly or seem to be insufficient, using the DOM and JavaScript can enrich the way you style your web documents. In this case, a combination of CSS and scripting techniques can be justified.

Using proprietary DOM to calculate heights#section6

It seems that browser makers were watching each other when they created their proprietary height specifications. As a result, proprietary DOM offers us the possibility to calculate the height of the browser window and document elements. Although several browsers use different objects and properties, the following script will retrieve the window height of almost any modern browser correctly:

function getWindowHeight() {
  var windowHeight=0;
  if (typeof(window.innerHeight)=='number') {
    windowHeight=window.innerHeight;
  }
  else {
    if (document.documentElement&&
      document.documentElement.clientHeight) {
        windowHeight=
          document.documentElement.clientHeight;
    }
    else {
      if (document.body&&document;.body.clientHeight) {
        windowHeight=document.body.clientHeight;
      }
    }
  }
  return windowHeight;
}

The window.innerHeight property returns the window height for most modern browsers except Internet Explorer. Internet Explorer 6 in Standards mode uses document.documentElement.clientHeight to achieve the same. The document.body.clientHeight property returns the window height for Internet Explorer 4+ browsers.

With document.getElementById(elementId).offsetHeight you can retrieve the height of any element for all modern browsers.

Now you can calculate the height of the browser window and your document’s elements, you are able write a function to position your footer correctly.

Using the W3C DOM to position the footer#section7

Just because you use JavaScript, this doesn’t mean you cannot use CSS for positioning elements. The W3C DOM offers an interface to use style rules with JavaScript. This means you can describe JavaScript as if it were CSS, with the addition of some conditional logic and a few height calculations.

Start by marking up your page in its most simplified form, creating a content and a footer block:

<div id="content">...</div>
<div id="footer">...</div>

If the height of the content block and the footer together is bigger than the height of the viewport, the footer should follow the normal flow (static positioning). If this is not the case, your script has to position the footer at the bottom of the window. With relative positioning, you can move the footer downwards relative to its position in the current flow (you can also use absolute positioning to achieve this). Sounds like CSS, doesn’t it?

The following function describes what we just defined:

function setFooter() {
  if (document.getElementById) {
    var windowHeight=getWindowHeight();
    if (windowHeight>0) {
      var contentHeight=
        document.getElementById('content').offsetHeight;
      var footerElement= 
        document.getElementById('footer');
      var footerHeight=footerElement.offsetHeight;
      if (windowHeight-(contentHeight+footerHeight)>=0) {
        footerElement.style.position='relative';
        footerElement.style.top=(windowHeight-
          (contentHeight+footerHeight))+'px';
      }
      else {
        footerElement.style.position='static';
      }
    }
  }
}

Dissecting the setFooter() function#section8

The setFooter() function first retrieves the height of the viewport and stores it in the windowHeight variable:

var windowHeight = getWindowHeight();

Second it retrieves the height of the content element and the footer element:

var contentHeight=
  document.getElementById(‘content’).offsetHeight;
var footerElement=document.getElementById(‘footer’);
var footerHeight=footerElement.offsetHeight;

Next it decides if the height of the window is larger than the combined height of the content and footer:

if (windowHeight-(contentHeight+footerHeight)>=0)

If this is the case, it repositions the footer relative (to its place in the normal flow) at the bottom of the page:

footerElement.style.position=‘relative’;
footerElement.style.top=
  (windowHeight-(contentHeight+footerHeight))+‘px’;

If they do fill the height of the window, the element is repositioned static to follow the normal flow:

footerElement.style.position='static';

To make everything work include the getWindowHeight() function in your script and add two functions that call your setFooter() function at the moment our web document is loaded or resized:

window.onload = function() {
  setFooter();
}
window.onresize = function() {
  setFooter();
}

You may view the finished version in example 4. However, there is one little hiccup. Safari is unable to position an element relative (or absolute) when the onload function is called. To work around this issue, add the following style rule:

#footer {
  position: relative;
}

The technique works in all modern browsers without using hacks, a temporary advantage over the CSS only technique. If a browser cannot calculate one of the heights, if JavaScript is switched off or if a browser doesn’t support JavaScript, the footer will just follow the normal flow. As you can see, structural mark-up and style are still separated and your marked-up code didn’t get more complicated. Maybe scripting tends to be more verbose than CSS, but not in a significant way.

Reusing the concept#section9

Just by making minor changes in the CSS logic, you have multiple ways to position your footer. You can use relative-positioned elements only (example 5) or absolute positioning (example 6).

The scripting technique can easily be reused for other vertical positioning tasks. Picture that you want to center a content block vertically in your browser window using CSS only. You could also have achieved this effect by reusing the scripting technique. You may view the result in example 7.

119 Reader Comments

  1. Much as I agree with the separation of presentation from content it is truly sad that the designers of css failed adequately to address some of the most basic aspects of page design, namely positioning. Positioning is a mental horror story. It is non intuitive and even though it gives the illusion of being easy it is actually really hard to pick up on the fly.

    Why on earth are elements which have spatial properties suddenly denied those properties the moment they’re positioned? And

    appears to have different default margins to … etc etc. You solve the problem for one website and when you move on to the next one suddenly you find that you have learnt nothing. The time wasted is astronomic.

    Sure, the solutions when implemented are really simple (or appear that way) but getting to that solution is just a nightmare. I have years of computing experience and all the help I need in the form of Hakon Lie and Bert Bos’ book “CSS designing for the web” and a host of links to useful sites, and membership of relevant discussion boards and still my head hurts.

    I havn’t the time but someone should write a good critique of css so that people like me can read it from time to time to releve the tension it causes. The fact of the matter is that browser differences with respect to javascript, dom, html, xhtml, css have turned web programming from what it ought to be – a really great experience – into a boring, dispiriting and morale destroying chore. At the very least we have Perl and Php to generate this stuff but boy it gets to me the extent to which my life is pouring into this machine and the little I’m left with to show for it – not even fun.

    Thanks for the space in which to explode.

  2. I’m trying to design a site without the use of tables and I found your article and the discussions that followed it very useful. I don’t have much experience with CSS or for that matter JavaScript and I’m going nuts trying to get this page to load properly. I have been looking at lots of different examples and pulling in bits of code from various places and therefore my code/style sheet looks like a dogs dinner!

    http://dev2.beckoz.com/CSStesting/

    My main problem is the footer hanging off the bottom of the page. I don’t know if the problem is in the CSS or the JavaScript (probably both!). Any help would be much appreciated.

  3. Tucker,

    First: only use one of the methods described in the article, not both. You should base your decision which one to use on the targeted audience you would like to serve. In this case you have to decide if you want the footer effect to be there for Mac users too (DOM/JavaScript method) or not (CSS method).

    Second: make sure you nest all your page elements inside either the main content block or the footer block. Except for the body and container div element for the CSS method, you shouldn’t need any elements outside these blocks.

    Third: the best way to develop a website using the footer (or any other) technique is by starting small with the basic technique (you could use the finshed examples as a template) and slowly building up your page. If something breaks you can easily see what element causes the error.

    If you have built a page that works fine and after an update it breaks, you should test it the other way around; you reduce code to see what causes the problem.

    In your case I would start over keeping points 1 to 3 in mind. It sounds like the hard way, but the best way to learn a new technology is to learn from your own mistakes.

    Please let me know how you proceed, if you get stuck again, I will help you on your way.

  4. Thanks for your help Bobby. I have gone for the CSS method to keep it as simple as possible for me and I have started again. But I’m still having problems!! :o(

    http://dev2.beckoz.com/CSStesting/attempt3.htm

    I have intentionally left the content background blue as a visual aid. My main 2 queries are:

    1. How do I make the content area stretch down to meet the footer? The only way I could get this to work was by making the height of #inner 100%, but this caused the footer to disappear off the bottom of the page! Have you any other suggestions?

    2. How do I get the footer to have a width of 100% of the screen? The footer sits within #container which has margin:0px 20px 0px 14px; The only way I could get it to stretch across was to make it 106% but it didn’t look right! You’ll see that I have put in margin-left: -50px; but this didn’t make any difference. Where am I going wrong?

    Your help is much appreciated.

  5. This version already looks way better. The footer technique is in place and working.

    Tucker said: “1. How do I make the content area stretch down to meet the footer?”

    You shouldn’t. The theory behind the technique is that only content stretches up the content area vertically.

    However if you want some visual effects that stretch up, you can always use the backgrounds of parent blocks that do stretch up to the footer (or actually the bottom of the page), like body and container.

    Here you need to plan your layout a little bit ahead. You start with the background of the most backwards layer and basically stack up background colors and (repeated) images of contained blocks until you have built up your layout. It always involves a little bit of puzzling, but I believe that any layout is possible this way.

    Tucker said: “2. How do I get the footer to have a width of 100% of the screen?”

    Just get rid of the margins of your container block and the negative margins of your footer block.

    The container should be the null point for positioning, so position all your elements relative to this block. You can always use other subcontainer blocks within your main container to position grouped elements.

    Hope this clears up the skies.

  6. Cheers Bobby for your last response. It looks like it’s now working but I have noticed than when I’m resizing the browser window all the text/content sometimes flashes/disappears! Is this something that I have done or is it just a quirk of the browser?

    http://dev2.beckoz.com/CSStesting/attempt4.htm
    I’ve also noticed a big jump in the content when the page is refreshed; I thought at first this might be due to FOUC ( see http://www.bluerobot.com/web/css/fouc.asp ) but after doing some testing it doesn’t appear to be, any ideas?

  7. I didn’t encounter the issue on IE6 and Firefox 0.8 both on WIN2K. It maybe has something to do with the browser/OS combi you are testing with.

    However in this version you broke the footer technique in non-IE browsers. Probable cause is the height: 80% that you added to your #inner block. I advise you to test your layouts in multiple browsers, so you can see where things go wrong.

    Next two small things to take care of:
    1. Get rid of the margin-bottom of -1px of your #footer block, it causes that a scrollbar is displayed in non-IE browsers
    2. Get rid of the duplicate tag

  8. The article starts with “Picture a container with a fixed width”.. but as soon as I apply a specific width to the container, the effect is canceled and the footer jumps back to the top. I browsed around this discussion area but did not find any info on this. Can anyone comment?

    Thanks

  9. Thanks for the second part, that is just what I needed for a project I’m working on. I now am able to keep the form’s reset and submit buttons in the viewport while the user scrolls through the form. You really should put a note in the article about this and not keep it buried in the comments. At first I tried the code from the article and it didn’t appear to do anything, since the form was longer than the viewport. Then I remembered sometimes revised methods are posted in the comments and I found what worked for me:
    http://www.bobbyvandersluis.com/articles/ala_footer_variation2.html

  10. When trying to print it only prints the viewport contents and not the entire page. Is there a way to fix this?

  11. Will, you can customize your print-outs by using a print style sheet.

    With something like:

    you should be king again.

  12. I had been looking for something similiar for quite a while. As more design orientated myself, as my JS skills are limited, having a footer placed in such a manner helps the look of the site, but yes it is a headache.

    Just a comment on my issue and how I resolved it for people who may come across it themselves. My content is not at the edge, it is offset by using the position absolute, and a left and top value. This posed a major issue with the script as it would obviously not see this and the footer would go over the text. If you defined a top value it would make the footer vanish completely. I tried using margins, margin-top would cause an issue too. I used &nbsp (no break white space) to position it properly, which is bad obviously as a web designer! But I managed to come up with a solution, so for anyone with the same issue.. just change the following line in the function setFooter(); … var contentHeight = document.getElementById(‘content’).offsetHeight + document.getElementById(‘content’).offsetTop; … it adds the offsetTop and pronto works. Sorry post is a bit long!

    Thanks again for such a great solution to a simple problem!

  13. Great article, but one slight glitch, when you resize the text.

    Especially bad in Mozilla and Netscape, no scroll bar, when you resize the text, no way you can see footer when it moves down the page.

  14. hi,
    i’m not programmer at all, just designer,
    my problem is simple as possible:
    i have 2 tables : the first must be center dead, the second must be footer all time and disapear behind the centering table if height not enought…
    the page here :
    http://www.portfolio360vr.com/folios/test8.htm

    checked with
    http://www.danvine.com/icapture/
    and “ie capture” on same page..
    seems good behaviors on all browser except opera…

    i’ve tried way of table inside of table(old method) and your css+jscript but my knowledges with programming is very poor and if someone could help me , peep a look inside the source page to see what’s wrong with opera wich keep the footer as header

    thanxs for help very much appreciated

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

I am a creative.

A List Apart founder and web design OG Zeldman ponders the moments of inspiration, the hours of plodding, and the ultimate mystery at the heart of a creative career.
Career