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:

<script src="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:#d22 5px 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>
    <div class="spacer"></div>
    <div id="firstHeader">Header 1</div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div id="secondHeader">Header 2</div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
    <div class="spacer"></div>
</body>

JS

function scrollFunction(){
    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
        });
    }
    else if(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
        });
    }
    else if(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;

function scrollFunction(){

    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
        });
    }
    else if(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
        });
    }
    else if(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 = new Array();

function scrollFunction(){

    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
                });
                return false;
            }
            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

<header class="default">
  <div class="default-cnt">
    Default Content
  </div>
  <div class="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');
      });
    } 
    else if($(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"