Sticky Header after scrolling down

114,962

Solution 1

Here's a start. Basically, we copy the header on load, and then check (using .scrollTop() or window.scrollY) to see when the user scrolls beyond a point (e.g. 200pixels). Then we simply toggle a class (in this case .down) which moves the original into view.

Lastly all we need to do is apply a transition: top 0.2s ease-in to our clone, so that when it's in the .down state it slides into view. Dunked does it better, but with a little playing around it's easy to configure

CSS

header {
  position: relative;
  width: 100%;
  height: 60px;
}

header.clone {
  position: fixed;
  top: -65px;
  left: 0;
  right: 0;
  z-index: 999;
  transition: 0.2s top cubic-bezier(.3,.73,.3,.74);
}

body.down header.clone {
  top: 0;
}

either Vanilla JS (polyfill as required)

var sticky = {
  sticky_after: 200,
  init: function() {
    this.header = document.getElementsByTagName("header")[0];
    this.clone = this.header.cloneNode(true);
    this.clone.classList.add("clone");
    this.header.insertBefore(this.clone);
    this.scroll();
    this.events();
  },

  scroll: function() {
    if(window.scrollY > this.sticky_after) {
      document.body.classList.add("down");
    }
    else {
      document.body.classList.remove("down");
    }
  },

  events: function() {
    window.addEventListener("scroll", this.scroll.bind(this));
  }
};

document.addEventListener("DOMContentLoaded", sticky.init.bind(sticky));

or jQuery

$(document).ready(function() {
  var $header = $("header"),
      $clone = $header.before($header.clone().addClass("clone"));

  $(window).on("scroll", function() {
    var fromTop = $("body").scrollTop();
    $('body').toggleClass("down", (fromTop > 200));
  });
});

Newer Reflections

Whilst the above answers the OP's original question of "How does Dunked achieve this effect?", I wouldn't recommend this approach. For starters, copying the entire top navigation could be pretty costly, and there's no real reason why we can't use the original (with a little bit of work).

Furthermore, Paul Irish and others, have written about how animating with translate() is better than animating with top. Not only is it more performant, but it also means that you don't need to know the exact height of your element. The above solution would be modified with the following (See JSFiddle):

header.clone {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  transform: translateY(-100%);
  transition: 0.2s transform cubic-bezier(.3,.73,.3,.74);
}

body.down header.clone {
  transform: translateY(0);
}

The only drawback with using transforms is, that whilst browser support is pretty good, you'll probably want to add vendor prefixed versions to maximize compatibility.

Solution 2

Here is a JS fiddle http://jsfiddle.net/ke9kW/1/

As the others say, set the header to fixed, and start it with display: none

then jQuery

$(window).scroll(function () {
  if ( $(this).scrollTop() > 200 && !$('header').hasClass('open') ) {
    $('header').addClass('open');
    $('header').slideDown();
   } else if ( $(this).scrollTop() <= 200 ) {
    $('header').removeClass('open');
    $('header').slideUp();
  }
});

where 200 is the height in pixels you'd like it to move down at. The addition of the open class is to allow us to run an elseif instead of just else, so some of the code doesn't unnecessarily run on every scrollevent, save a lil bit of memory

Solution 3

Here's is quite a list of jQuery plugins that will help achieve similar effect: http://jquery-plugins.net/tag/sticky-scroll

Solution 4

I suggest to use sticky js it's have best option ever i have seen. nothing to do just ad this js on you

 https://raw.githubusercontent.com/garand/sticky/master/jquery.sticky.js

and use below code :

<script>
  $(document).ready(function(){
    $("#sticker").sticky({topSpacing:0});
  });
</script>

Its git repo: https://github.com/garand/sticky

Solution 5

Here's a simple solution without jQuery only Vanilla JS.

In the example, we just use "header" class that you can change to anything else you want. Basically, it makes a clone of the existing header and shows it down below as a fixed header.

The solution is fast since the animation is done with CSS transitions and no additional JS animation overhead.

You can tweak the animation styles to have your own transition. Animation "slidein" is used for showing the fixed header on scroll down, and "slideout" when you want it to disappear when you scroll up to the top.

(function() {

  //CONFIGURATION
  var headerClassName = 'header'; //Class of your header element
  var stickyAfter = 150; //Show fixed header after this Y offset in px
  
  var header = document.getElementsByClassName(headerClassName)[0];
  var clone = header.cloneNode(true); 
  clone.classList.add('clone'); 
  header.parentElement.appendChild(clone);
  
  var initializeHeader = function() {
    document
    .getElementsByClassName(headerClassName + ' clone')[0]
    .classList.add('initialized');
    return true;
  }
  
  window.onscroll = function() {
    var cl = document.body.classList;
    window.pageYOffset > stickyAfter ? 
      initializeHeader() && cl.add('sticky') : 
      cl.remove('sticky');
  } 

})();
/* GENERAL STYLES */
body {
  min-height: 2000px;
}
.header {
  background: green;
  padding: 7px 20px;
  color: #fff;
  position: relative;
  min-width: 100%;
}

/* STICKY HEADER STYLES */
@keyframes slidein {
  from {
    position: fixed;
    top: -50px;
    opacity: 0;
  }
  to {
    position: fixed;
    top: 0;
    opacity: 1;
  }
}
@keyframes slideout {
  from {
    position: fixed;
    top: 0;
    opacity: 1;
  }
  to {
    position: fixed;
    top: -50px;
    opacity: 0;
  }
}
.header.clone.initialized {
  -webkit-animation: slideout .3s forwards; /* for less modern browsers */
   animation: slideout .3s forwards;
}
body.sticky .header.clone {
  -webkit-animation: slidein .3s forwards; /* for less modern browsers */
   animation: slidein .3s forwards;
}
<div class="header">
  <p>This is demo header</p>
</div>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc mollis augue vel massa dictum gravida. Ut vitae elit ligula. In vitae sagittis lacus. Curabitur vel magna eget mauris vestibulum vestibulum id eget dui. Morbi tempus laoreet gravida. Curabitur vel volutpat lacus. Morbi dictum iaculis nibh. Praesent cursus tempor placerat. Sed posuere dui et diam elementum luctus. Nulla aliquet vestibulum justo.</p>

<p>Integer cursus tellus nec sodales lobortis. Donec dictum pharetra ligula, at lobortis lorem pellentesque non. Nullam volutpat nisi id laoreet condimentum. Morbi vel erat vitae elit sodales iaculis ac ut libero. Cras eget neque at libero feugiat interdum. Praesent eget erat mauris. Maecenas convallis aliquet risus non tempus.</p>

<p>Sed convallis elit a dignissim vestibulum. Quisque pharetra, leo eu eleifend pretium, dolor enim viverra elit, quis aliquet dui lacus sit amet dolor. Quisque sit amet sapien tellus. Nam tristique placerat dui, placerat fringilla magna varius nec. Ut id arcu metus. Aenean eu mollis massa. Vestibulum cursus egestas turpis, a tempor metus mattis eu. Donec fringilla quam non fermentum fringilla.</p>

<p>Nam et lorem leo. Donec libero tortor, laoreet quis maximus at, faucibus fermentum ligula. Curabitur facilisis quam in posuere suscipit. Ut sagittis mauris ullamcorper, feugiat sem sed, egestas lorem. Curabitur ut urna laoreet, commodo dolor id, blandit arcu. Aliquam vitae odio magna. Curabitur eu mi dolor. Praesent tellus lectus, mattis eu nunc ac, sagittis tincidunt nulla.</p>

<p>Morbi augue erat, consectetur non pulvinar et, auctor id mi. Vestibulum a ornare diam, nec dignissim neque. Aliquam sodales orci vitae lorem rhoncus, cursus fermentum nisl hendrerit. Aliquam erat volutpat. Mauris fermentum cursus arcu, in imperdiet lacus ultrices ut. Vivamus ligula nulla, mollis a consequat id, varius sed odio. Proin sed fringilla nunc, at dignissim ipsum. Etiam dictum tortor turpis, ac ornare purus semper non. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec a urna vitae metus vestibulum tincidunt sed gravida metus. Vivamus auctor sed leo eget lacinia. Nulla quis bibendum erat. Nunc dapibus lobortis odio, vel porttitor dui elementum at. Ut neque libero, rutrum vel cursus id, rhoncus vitae felis.</p>
Share:
114,962
Nepo Znat
Author by

Nepo Znat

🐍

Updated on July 30, 2021

Comments

  • Nepo Znat
    Nepo Znat almost 3 years

    I saw this sticky header on this website: http://dunked.com/ (no longer active, view archived site)

    When you scroll down the sticky header comes down from the top.

    I looked at the code, but it looks really complicated. I only understand this: The normal header was cloned with JS and when you scroll down the page it animates from top.

  • joevallender
    joevallender almost 11 years
    Ah, I can see that the same header is re-used on the example, this works for one header inline and one for drop down (handy if you wanted a simpler,smaller strip after scroll) but you get the idea!
  • Nepo Znat
    Nepo Znat almost 11 years
    In Firefox it works good but in chrome not. But thank you - it helped me a lot.
  • Ian Clark
    Ian Clark almost 11 years
    @user2416687 Ah, looks like some quirk of having a Fiddle use an iFrame - I've changed to use window (see this question)
  • Ian Clark
    Ian Clark almost 11 years
    Oh, and - anytime, I tried to break it down to explain what was going on :)
  • John Ruddell
    John Ruddell about 9 years
    scrollToFixed() is a really good one in that list. does exactly waht I want. a header that stays in place untill I scroll past it them its stuck to the top of the page. very useful!
  • kano
    kano over 8 years
    This really ought to be a comment and not a valid answer by any stretch.
  • Admin
    Admin about 7 years
    I believe you meant 'fixed', because that is not how sticky works.
  • erier
    erier about 7 years
    Fair - but the debounce is relevant to best practice when solving the issue. +1 from me