Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sticky Header - buggy jumping on scroll

I have a specific problem on making a sticky header with jQuery. I tried the commonly used snippets around the web, but I perceived the same buggy thing everywhere.

At a specific document height (scrollable until a little more than calling of sticky-effect) the sticky header jumps between position: fixed and position: static.

HTML:

<header>
  <div id="not-sticky"></div>
  <div id="sticky"></div>
</header>
<div id="content"> ...


jQuery:

var $sticky = $("#sticky");
var offset = $sticky.offset();
var stickyTop = offset.top;
var windowTop = $(window).scrollTop();
$(window).scroll(function() {
  windowTop = $(window).scrollTop();
  if (windowTop > stickyTop) {
    $sticky.css({
      position: 'fixed',
      top: 0
    });
  }
  else {
    $sticky.css({
      position: '',
      top: ''
    });
  }
});


CSS:

header {
  width: 100%;
}

#not-sticky {
  padding: 50px 0;
  width: 100%;
}

#sticky {
  padding: 24px 0;
  position: relative;
  width: 100%;
  z-index: 25;
}


I also tried a margin-bottom on #not-sticky with the same height as the #sticky to keep a constant document-height, but the same jumpy-sticky-effect occurred.

Any idea to fix that thing?

like image 626
Timo Mämecke Avatar asked May 13 '13 01:05

Timo Mämecke


People also ask

What is sticky scrolling?

The Sticky Scrolling Effect lets you set a Section/Widget as sticky, so that it sticks to the top or bottom of the screen. Watch a video of a cool example of a sticky scrolling effect.

How do I stop my header from sticking?

Log into WordPress and go to Appearance > Customize > General Theme Settings > Header and uncheck the option.

Why are my headers sticky?

When done appropriately, sticky headers allow users to quickly access the navigation, search, and utility-navigation elements without scrolling up to the top of the page. They increase the discoverability of the elements in the header and the chance that users will take advantage of them.


1 Answers

Scroll fires too many times and trying to set an element style will always & inevitably create jumps (even barely noticeable but still jaggy).

The best way I've found is to

  1. clone our element,
  2. make that clone fixed
  3. play with clone's visibility style.

Pure JS:

;(function(){ /* STICKY */

  var sticky  = document.getElementById("sticky"),
      sticky2 = sticky.cloneNode(true);

  sticky2.style.position = "fixed";
  document.body.appendChild(sticky2);

  function stickIt(){
    sticky2.style.visibility = sticky.getBoundingClientRect().top<0 ? "visible" : "hidden";
  }

  stickIt();
  window.addEventListener("scroll", stickIt, false );
}());
#sticky{
  height:100px;
  background:#ada;
  height:50px;
  position:relative;
  /* needed for clone: */
  top:0; 
  width:100%;
}


/* Just for this demo: */
*{margin:0;padding:0;}
#content{height:2000px; border:3px dashed #444;}
h1{padding:40px; background:#888;}
<h1>Logo</h1>
<div id="sticky">Sticky header</div>
<div id="content">Lorem ipsum...<br>bla bla</div>

So when you see the "header" fix, that's actually our fixed clone getting visible on-top.

like image 152
Roko C. Buljan Avatar answered Sep 24 '22 18:09

Roko C. Buljan