Skip to content Skip to sidebar Skip to footer

Replacing A Sticky Header With A Second Header When It Reaches The Currently Stuck Header

I've been reading up on sticky headers and this is what I've found so far. The first sticky header works great but how could I scroll the first header up and make the second header

Solution 1:

I believe that the following will do exactly as you want...

The #firstHeader will bind to the top when scrolled past, and then when the #secondHeader collides with the bottom of the #firstHheader they will join and the #firstHeader will be pushed off of the screen until the #secondHeader reaches the top of the screen and binds there...

Hopefully that makes sense, if not, it'll probably be easier if you see it in action: http://jsfiddle.net/yZKea/

This solution does use jquery. So you'll need to include a reference to it in your head before the rest of the JS code:

<scriptsrc="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

NOTE: The JS isn't as daunting or as long as it looks, most of it is repeated setting of styles. You could easily change it to just a few lines :)

CSS

html, body {
    margin: 0;
    padding: 0;
    border: 0;
}
.spacer{
    height:200px;
    background:#f00;
    opacity:.5;
    border-top:#d225px solid;
    width: 100%;
}
#firstHeader{
    background:#00f;
    height: 100px;
    width: 100%;
    z-index:500;
}
#secondHeader{
    background:#0f0;
    height: 100px;
    width: 100%;
    z-index:500;
}

HTML

<body><divclass="spacer"></div><divid="firstHeader">Header 1</div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divid="secondHeader">Header 2</div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div><divclass="spacer"></div></body>

JS

functionscrollFunction(){
    var sticky1 = $('#firstHeader');
    var sticky2 = $('#secondHeader');

    sticky1.css({
        position: "static",
        top: 0
    });
    sticky2.css({
        position: "static",
        top: 0
    });
    $('body').css({
        "padding-top": 0
    });

    var topOffset1 = sticky1.offset().top;
    var topOffset2 = sticky2.offset().top;

    var stickyHeight1 = sticky1.outerHeight();
    var stickyHeight2 = sticky2.outerHeight();

    var scrollHeight = $(window).scrollTop();

    if(topOffset1 <= scrollHeight && scrollHeight < topOffset2 - stickyHeight1){
        sticky1.css({
            position: "fixed",
            top: 0
        });
        sticky2.css({
            position: "static",
            top: 0
        });
        $('body').css({
            "padding-top": stickyHeight1
        });
    }
    elseif(scrollHeight >= topOffset2 - stickyHeight1 && scrollHeight < topOffset2){
        sticky1.css({
            position: "fixed",
            top: - (scrollHeight - (topOffset2 - stickyHeight1))
        });
         sticky2.css({
            position: "fixed",
            top: stickyHeight1 - (scrollHeight - (topOffset2 - stickyHeight1))
        });
        $('body').css({
            "padding-top": stickyHeight1 + stickyHeight2
        });
    }
    elseif(scrollHeight >=  topOffset2){
        sticky1.css({
            position: "static"
        });
         sticky2.css({
            position: "fixed",
            top: 0
        });
        $('body').css({
            "padding-top": stickyHeight2
        });
    }
    else{
        sticky1.css({
            position: "static",
            top: 0
        });
        sticky2.css({
            position: "static",
            top: 0
        });
        $('body').css({
            "padding-top": 0
        });
    }

}

$(window).scroll(scrollFunction);

Updated JS

This should solve the problem with having a flickery screen.

var topOffset1, topOffset2;

functionscrollFunction(){

    var sticky1 = $('#firstHeader');
    var sticky2 = $('#secondHeader');

    var stickyHeight1 = sticky1.outerHeight();
    var stickyHeight2 = sticky2.outerHeight();

    var scrollHeight = $(window).scrollTop();

    if(topOffset1 <= scrollHeight && scrollHeight < topOffset2 - stickyHeight1){
        sticky1.css({
            position: "fixed",
            top: 0
        });
        sticky2.css({
            position: "static",
            top: 0
        });
        $('body').css({
            "padding-top": stickyHeight1
        });
    }
    elseif(scrollHeight >= topOffset2 - stickyHeight1 && scrollHeight < topOffset2){
        sticky1.css({
            position: "fixed",
            top: - (scrollHeight - (topOffset2 - stickyHeight1))
        });
         sticky2.css({
            position: "fixed",
            top: stickyHeight1 - (scrollHeight - (topOffset2 - stickyHeight1))
        });
        $('body').css({
            "padding-top": stickyHeight1 + stickyHeight2
        });
    }
    elseif(scrollHeight >=  topOffset2){
        sticky1.css({
            position: "static"
        });
         sticky2.css({
            position: "fixed",
            top: 0
        });
        $('body').css({
            "padding-top": stickyHeight2
        });
    }
    else{
        sticky1.css({
            position: "static",
            top: 0
        });
        sticky2.css({
            position: "static",
            top: 0
        });
        $('body').css({
            "padding-top": 0
        });
    }

}

$(function(){
    topOffset1 = $('#firstHeader').offset().top;
    topOffset2 = $('#secondHeader').offset().top;
});

$(window).scroll(scrollFunction);

JS For variable number of headers

Simply add the class .header to your headers and this will work for any number of headers (1, 5, 100... You get the point).

This is a complete replacement for the above JS and each new header will push the old header off of the screen before it binds to the top.

See this updated jsfiddle for an example of it in action: http://jsfiddle.net/5bkst/

var topOffset = newArray();

functionscrollFunction(){

    var scrollHeight = $(window).scrollTop();
    var headerCounter = 0;
    var scrolled      = 0;
    var headerItems   = $('.header').length;

    $('.header').each(function(index, el){

        var elementHeight = $(this).outerHeight();

        var nextElementHeight = 0;
        var nextElement;

        if(index !== $('.header').length - 1){
            nextElementHeight = $('.header').eq(index + 1).outerHeight();
            nextElement       = $('.header').eq(index + 1);
        }

        if(scrollHeight >= topOffset[headerCounter]
            && (scrollHeight < topOffset[headerCounter + 1] || headerCounter == headerItems-1)){

            scrolled = 1;

            if(scrollHeight >= topOffset[headerCounter + 1] - elementHeight){
                $(this).css({
                    position: "fixed",
                    top: - (scrollHeight - (topOffset[headerCounter + 1] - elementHeight))
                });
                nextElement.css({
                    position: "fixed",
                    top: topOffset[headerCounter + 1] - scrollHeight
                });
                $('body').css({
                    "padding-top": elementHeight + nextElementHeight
                });
                returnfalse;
            }
            else{
                $(this).css({
                    position: "fixed",
                    top: 0
                });
                nextElement.css({
                    position: "static",
                });
                $('body').css({
                    "padding-top": elementHeight
                });
            }

        }
        else{
            $(this).css({
                position: "static"
            });
        }

        headerCounter++;
    });

    if(scrolled == 0){
        $('body').css({
            "padding-top": 0
        });
    }
}

$(function(){
    $('.header').each(function(){
        topOffset.push($(this).offset().top);
    });
});

$(window).scroll(scrollFunction);

Solution 2:

If you want to switch headers than try this. FIDDLE

<headerclass="default"><divclass="default-cnt">
    Default Content
  </div><divclass="fixed-cnt">
    Fixed Content
  </div></header>

header {
  width: 100%;
  height: 120px;
  padding: 10px;
  letter-spacing: 1px;
}
.default {
  background: #555;
  position: relative;
  color: #fff;
}
.fixed {
  background: #01a8e7;
  position: fixed;
  top: 0;
  left: 0;
  color: #000;
}
.default.fixed-cnt {
  display: none;
}
.fixed.default-cnt {
display: none;
}

$(function() {
  var header = $('header');
  var headOff = header.offset();

  $(window).scroll(function() {
    if($(this).scrollTop() > 120 + headOff.top && header.hasClass('default')) {
      header.fadeOut('fast', function() {
        $(this).removeClass('default').addClass('fixed').fadeIn('fast');
      });
    } 
    elseif($(this).scrollTop() <= 120 + header.height() && header.hasClass('fixed')) {
      header.fadeOut('fast', function() {
        $(this).removeClass('fixed').addClass('default').fadeIn('fast');
      });
    }
  });
});

Post a Comment for "Replacing A Sticky Header With A Second Header When It Reaches The Currently Stuck Header"