Fixed on Scroll Animated Header With CSS and JavaScript

In this post I will explain how to create an animated sticky header, with CSS3 and JavaScript. So we are going to have a header that will behave normally until we have to scroll and then it will become smaller but still stick to the top of the viewport.

The HTML

For this example all we need is a header with an h1 and the main div which holds the content that we can scroll over.

1
2
3
4
5
6
7
8
<body>
  <header>
    <h1>Animated Sticky Header</h1>
  </header>
  <div id="main">
      <p> Curabitur quam neque, malesuada sit amet justo ut, posuere pretium quam. In laoreet nunc velit. Nam mattis erat et leo mollis, sed pulvinar lectus volutpat. Phasellus mi eros, sollicitudin non elit sed, molestie viverra eros. Nullam facilisis mauris ante, sed vulputate sapien efficitur quis. Curabitur vitae lorem eros. Fusce orci odio, eleifend et sem luctus, bibendum viverra nibh. Proin vitae libero egestas, consequat orci id, facilisis ex. Quisque lectus dui, mattis non lectus ac, finibus facilisis velit. Integer mauris nibh, suscipit eu egestas nec, placerat scelerisque purus. Nulla facilisi. Proin eleifend, lectus eget rutrum luctus, dolor nunc luctus ex, sed consequat urna nisi ac ipsum.In hac habitasse platea dictumst.<p>
  </div>
</body>

The CSS

In order to make the header sticky we have to fix it’s position to the top of the viewport, hide any overflow and make sure it is always visible by setting the z-index of the header:

1
2
3
4
5
overflow: hidden;
position: fixed;
top: 0;
left: 0;
z-index: 999;

This will now keep the header always at the top and visible.

The animation of the header can be achived by having a different style rule for when the user has scrolled down -.smaller class. We cna detect if the user has scrolled down using JavaScript (described below) and apply the .smaller class to the <header>. When the header is smaller, we are reducing its height and the font size of the <h1>. This is now the full CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  min-height: 100%;
}

header {
  background: #F58065;
  padding: 0.75em;
  height: 4em;
  color: #fcfcfc;
  overflow: hidden;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
  width: 100%;
}

h1 {
  max-width: 70%;
  margin: 0 auto;
  font-size: 2em;
}

.smaller {
  height: 2em;
}

.smaller h1 {
  font-size: 1em;
}

p {
  max-width: 70%;
  margin: 0 auto;
  min-height:700px; /**this is just to force scrolling since we don't have much content**/
}

#main {
  display: block;
  padding-top: 8em;
}

The JavaScript

As mentioned above, in order to animate the header we have to detect of the user is scrolling. This can be achieved by checking if the pageYOffset or the value received from the document.documentElement.scrollTop the returned value is the distance scrolled in pixels.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function init() {
window.addEventListener('scroll', function(e){
  var distanceY = getScrollTop(),
      shrinkOn = 20,
      header = document.querySelector("header");
  if (distanceY > shrinkOn) {
    header.setAttribute("class","smaller");
  } else {
      header.removeAttribute("class");
  }
});
}

function getScrollTop() {
  if(typeof pageYOffset != 'undefined'){
      //most browsers except IE before 9
      return pageYOffset;
  }
  else {
      var B = document.body; //IE 'quirks'
      var D = document.documentElement; //IE with DOCTYPE
      D = (D.clientHeight)? D: B;
      return D.scrollTop;
  }
}
window.onload = init();