title: jQuery (or other javascript) to stack divs at fixed distance from top of viewport
body: <p>I would like it so that the as the user scrolls down the page and hits certain "sticky" elements, they add themselves to the top of the page.</p>
  
  <p>I.e., let's say the page has a fixed, 10px high element at the top, then a 50px high Logo (non sticky), then a horizontal navigation bar (sticky), then some other non-sticky elements, then a pager (sticky, allows user to go to next or previous page), etc.</p>
  
  <p>The idea is that some elements are useful all up and down the page, others can just stay at the top. But since they are intercalated, we need a way to stick just the important ones to the top.</p>
  
  <p>So, if you scrolled halfway down the page, the non stick elements would have moved out of view, but the sticky ones would all be stacked at the top below any fixed element. In my example, you'd have 10px high element, nav bar, and pager. The logo would scroll away.</p>
  
  <p>I've come up with some jQuery but it's quirky. If I scroll down slowly, it works. If I scroll down quickly, or hit "page down" on my keyboard, it ends up working incorrectly, with extra space between sticky elements and other errors.</p>
  
  <p>It feels like I'm so close, and yet so far.</p>
  
  <p>Here's what I have. </p>
  
  <pre><code>&lt;style type="text/css"&gt;
  div.stickert {
      /*
      padding:20px;
      margin:20px 0;*/
      /*background:#AAA;
      width:190px;*/
      position:relative;
      top:0px;
  }
  .sticked {
      position:fixed;
      /*top:0px;
      z-index:100;*/
      width:100%;
  }
  &lt;/style&gt;
  &lt;!--&lt;script src="http://code.jquery.com/jquery-latest.min.js"&gt;&lt;/script&gt;--&gt;
  &lt;script type="text/javascript"&gt;
  jQuery(document).ready(function() {
      var stupid = jQuery(".stickert");
      var startOffset = 0;
      var startingZ = 100;
  
  
  /*  var topDone = []; */
  /*  var pos = second.position();  */
      var origOffsets = [];
      var heights = [];
      var currentOffsets = [];
      mWait = jQuery("#m-wait");
      mWait.show();
      mGraph = mWait.find('p');
      mGraph.text('');
  
      jQuery.each(stupid, function(i, object) {
              var obj = jQuery(object);
              var pos = obj.position();
              origOffsets[ i ] = pos.top;
              heights[ i ] = obj.height();    
          } 
      );
      var debug = false;
      jQuery(window).scroll(function() {
          var windowpos = jQuery(window).scrollTop();
          var topOffset = startOffset;
          var theZIndex = startingZ;
          jQuery.each(stupid, function(i, object) { 
              var obj = jQuery(object);
              console.log(obj);
              /*mGraph.append('obj:&lt;br /&gt;' + obj);*/
              /*var pos = obj.position();*/
  /*          currentOffsets[ i ] = pos;*/
              var tagName = obj.get(0).tagName;
              tagName.toLowerCase; /* e.g. "div" or "li" */
              var totalOffset = parseInt(origOffsets[ i ],10) - parseInt(startOffset,10) - topOffset; /* I think subtraction is correct */
              if(windowpos &lt;= totalOffset /*&amp;&amp; obj.hasClass("sticked") */) {
                  if( debug ) alert('resetting');
                  if(obj.hasClass("sticked") ) {
  
                      obj.removeClass("sticked");
                      /*obj.addClass("stickert");*/               
                      obj.css({ top: "0px"  });
                      var removeThis = obj.next(".sticked-padder");
                      removeThis.remove();
                      obj.addClass("stickert"); /* put inside if hasclass? */
  
                  }
  
  
                  /* return false; */
              } else if(windowpos &gt; totalOffset) {
              /*if(windowpos &gt;= pos.top) {*/
                  /*if( debug ) alert("setting sticked");*/
  
                  /*if(!(i in topDone)) {*/
                  if(obj.hasClass("stickert")) {
                      mGraph.append('Element ' + i + '&lt;br /&gt;Made it to the start. zIndex = ' + theZIndex + '&lt;/br&gt;'
                          + 'topOffset= ' + topOffset + '&lt;br /&gt;');
                      obj.removeClass("stickert");                    
                      /*currentOffsets[ i ] = obj.position();*/
                      topOffset += obj.height();
                      if( debug ) alert(topOffset);
                      obj.after('&lt;' + tagName + ' class="sticked-padder" style="height:' + obj.height() + 'px"&gt;&lt;/div&gt;');                  
                      /*topDone[ i ] = "done";*/
  
                      obj.css({ top: ( topOffset - heights[ i ] ) + "px"});
                      obj.addClass("sticked");
                      obj.css({ zIndex: theZIndex });
                      theZIndex -=1 ;
                      mGraph.append('Element ' + i + '&lt;br /&gt;Made it to the end. zIndex = ' + theZIndex + '&lt;/br&gt;'
                      + 'topOffset= ' + topOffset + '&lt;br /&gt;');
                      /* alert(theZIndex);*/
                  }
  
  
  
              }
              topOffset += heights[ i ];          
          });
          jQuery(window).scrollTop(windowpos); /* make sure window stays in same place */
          /* ssss.html("Distance from top:" + pos.top + "&lt;br /&gt;Scroll position: " + windowpos); */
          /*if (windowpos &gt;= pos.top) {
              stupid.addClass("sticked");
          } else {
              stupid.removeClass("sticked");  
          }*/
      });
  });
  &lt;/script&gt;
  </code></pre>