Search code examples
javascriptfixedonscroll

Javascript Sticky Element onscroll avoid jumping


I'm trying to fix an element when I scroll down. The code works fine but as you can see at the following link, the bar with the 3 yellow buttons jumps when it is about to reach the Top! There seems to be some template css class causing this problem, but I can't figure out which one

This is the code

var fixmeTop = $('.pulsanti').offset().top;       

$(window).scroll(function() {                  

    var currentScroll = $(window).scrollTop(); 

    if (currentScroll >= fixmeTop) {          
        $('.pulsanti').css({                      
            position: 'fixed',
            top: '0',
            zIndex: '1020'
        });
    } else {                                   
        $('.pulsanti').css({              
            position: 'relative'
        });
    }

});

thank you everyone


Solution

  • I think the problem is that fixmeTop is assigned before some elements are loaded:

    var fixmeTop = $('.pulsanti').offset().top;
    

    My chrome console outputs this:

    > fixmeTop 
    < 2314.3374633789062
    > $('.pulsanti').offset().top; 
    < 3207.5623779296875
    

    You can see that the fixmeTop variable is not the real element position.

    Maybe you need to assign it in body.onload()?

    Update

    After executing fixmeTop = $('.pulsanti').offset().top; in the chrome console after the page is loaded, I can verify that the element is sticking smoothly to the top of the page.

    Adding this code fragment will create a handler function to be called when the window's load event fires. That will happen after everything (divs, images) is loaded. This way the fixmeTop will contain the true element position.

    window.onload = function () {
       fixmeTop = $('.pulsanti').offset().top;
    }
    

    You can keep the variable declaration in the original script, or remove it and add var here.

    Also, bear in mind that it will not work until everything on the page is loaded and that it will not be valid when anything on the page moves - eg. page resize, divs rearranged. You would have to add listeners for every such event to adjust the value accordingly. Something like this may be useful:

    function updateFixmeTop() {
        fixmeTop = $('.pulsanti').offset().top;
    }
    
    window.addEventListener("resize", updateFixmeTop);
    

    edit: changed element body to window in event listener

    Hope it helps!

    Update2

    Let's say you added the code for resize event listener and scrolled past the point where the element should stick to the top. If you were to resize window fixmeTop would be assigned a value that corresponds to the element being on top of the page, and not the original element position.

    To fix this you may want to add a dummy element without any margin or padding:

    <div id="elementJustBeforeFixmeTop"></div> <! -- dummy element -->
    <div class="pulsanti"> <! -- sticky element -->
        ...
    </div>
    

    And refer to its position instead of the sticky element

    fixmeTop = $('#elementJustBeforeFixmeTop').offset().top;
    

    This way you will store the scroll position at which you want the element to stick and it will not be different if the element is already at the top.

    You may want to check if your page doesn't change its layout somewhere else and also update the fixmeTop value there to ensure it's always pointing at the right element.