Nov
27
2013

Sticky Blocks (New updated code)

Earlier I did an article about how I created sticky blocks which scrolls along, when the pages are scrolled down (Sticky Blocks). Here is an update to that code. In earlier code, if an image is present in the content, the browsers fail to recognize the correct height of the content. This is because the height is taken before the images are loaded. A workaround for this is to execute the code after image load (as suggested in a stackoverflow thread).

What I did is I put the codes to make the blocks sticky inside a function "makeSticky()" and called this function after the image load. Also it is checked if any images are present in the content, if not it does not wait for the image load but directly call the makeSticky() function.

Here is the full code:

jQuery(document).ready(function($) {
  // Function to make the block sticky.
  function makeSticky(){
    var stickyIndex = $('.sticky-block').index();
    var stickyWidth = $(".sidebar").innerWidth();
    $('.sidebar .block').slice(stickyIndex).wrapAll('<div class="sticky-wrap"></div>'); // Add a wrap for sticky block and blocks below it.
    $('.sidebar .sticky-wrap').css({ 'width': stickyWidth}); // To avoid width of sticky wrap expand when position fixed is applied when scrolling.

    var sidebarHeight = $(".sidebar").height();
    var contentHeight = $(".content").height();
    if(contentHeight > sidebarHeight){
      sidebarHeight = contentHeight;
      $(".sidebar").height(sidebarHeight);
    }
    var sidebarTop = $('.sidebar').offset().top;
    var stickyHeight = $('.sidebar .sticky-wrap').height();
    var maxScroll = sidebarTop + (sidebarHeight - stickyHeight); // Max point where the scrolling should end. Sticky should should not scroll over footer content.
    var stickyTop = $('.sticky-block').offset().top;

    $(window).scroll(function(){ // Scroll event.
      var windowTop = $(window).scrollTop(); // Current scroll top position of window.

      if (stickyTop < windowTop && maxScroll > windowTop){ // When scrolling fix the block.
        $('.sidebar').css('position','static');
        $('.sticky-wrap').css({ 'position': 'fixed', 'top': '10px', 'z-index': 900 });
      }
      else if (maxScroll < windowTop){ // When scroll reaches end of sidebar stop scrolling.
        $('.sidebar').css('position','relative');
        $('.sticky-wrap').css({ 'position': 'absolute', 'top': 'auto', 'bottom': 0 });
      }
      else { // When sidebar top reached change everything back to normal.
        $('.sidebar').css('position','static');
        $('.sticky-wrap').css('position','static');
      }
    });
  }
  if (!!$('.sticky-block').offset()) { // Check if sticky block element exists,
    // To execute after images are loaded.
    if($(".content-wrapper img").length > 0){ // Check if there is image present inside container. The selector should be the container which wraps the content and sidebar.
      var img = $(".content-wrapper img"); // Get my img element
      $("<img/>") // Make in memory copy of image to avoid css issues
        .attr("src", $(img).attr("src"))
        .load(function() {
          makeSticky(); // function to make block sticky.
        });
    } else {
      makeSticky();
    }
  }
});