3

I've been using this snippet of jQuery to get a sticky footer:

if($(document.body).height() < $(window).height()){
        $("#footer").css({
            position: "absolute",
            top:  ( $(window).scrollTop() + $(window).height()
                  - $("#footer").height() ) + "px",
            width: "100%"
       });
}
$(window).scroll(positionFooter).resize(positionFooter);

However, that breaks when I've got expandable/collapsible divs lying around where the original content was less high than the window, since it is then stuck to the bottom of the window, rather than the bottom of the document.

Is there a way of fixing this, or a better way of doing it?

Please bear in mind that I don't have much control over the HTML, since I need to do this in Django's admin interface, which doesn't allow much injection of HTML in the places you might want to to accomplish this sort of thing (i.e. this answer and this answer don't work for me).

Community
  • 1
  • 1
Dominic Rodger
  • 97,747
  • 36
  • 197
  • 212

3 Answers3

11

So you don't want to position the footer absolutely anymore when the document height is higher than the window height? Then add an else statement which does exactly that:

if($(document.body).height() < $(window).height()){
    $('#footer').css({
        position: 'absolute',
        top:  ( $(window).scrollTop() + $(window).height()
              - $("#footer").height() ) + "px",
        width: "100%"
    });
} else {
    $('#footer').css({
        position: 'static'
    });
}   

Here's a live demo. Note that I added click event to $(window) because the resize doesn't get triggered in FF when you expand/collapse a div.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • +1 just what I thought. And don't forget to call `positionFooter()` when you toggle an element. – gblazex Jul 09 '10 at 13:20
  • @galam: That's taken care by adding `click` to `$(window)` event listener. This is by the way not needed for IE. – BalusC Jul 09 '10 at 13:25
  • @BalusC it works in most cases, but if there is an *ancestor* of the *toggler* element which stops *event bubbling*, then it won't get to `window` http://jsbin.com/ejabe – gblazex Jul 09 '10 at 13:51
  • @gala: that's pretty an edge case. – BalusC Jul 09 '10 at 13:54
  • @BalusC yes and no. :) Stopping even delegation can happen anywhere, intentionally or not. A simple `return false` is enough to break the code. Unfortunately I saw use cases where one's habit was to end every event handler like this (whether its appropriate or not). – gblazex Jul 09 '10 at 14:16
  • holy crap jsfiddle.net looks awesome. – Tim Coker Jul 14 '10 at 11:17
3

I used this approach to sticky footers and dynamic content (but my application was slightly more complicated to integrate than the examples) and it works: http://www.cssstickyfooter.com/

pablorc
  • 940
  • 1
  • 8
  • 20
0

I know I'm way late to the party, but I encountered a similar problem with both my AJAX comments and post/portfolio tag filters just recently. Google led me here, and the accepted answer inspired my first example below.

I set my sticky footer logic to fire for both document ready and window resize:

$(document).ready(function() {
  stickyFooter();
});
$(window).on('resize', function() {
  stickyFooter();
});

For my dynamic content, I can simply trigger a resize within the DOM-height-modifying function e.g.:

function dynamicFunctionOne() {
  /* DOM-height-modifying logic here */

  $(window).trigger('resize');
}

dynamicFunctionOne();

In another case I call my sticky footer function as a callback of another DOM-height-modifying function.

function dynamicFunctionTwo(callback) {
  /* DOM-height-modifying logic here */

  callback();
}

dynamicFunctionTwo(stickyFooter);

With either implementation, there's no need to listen for an event on every click that occurs to set the sticky footer's position.