Skip to content Skip to sidebar Skip to footer

Unexpected Jump While Changing Position From Absolute To Fixed, Why?

first of all I want to say that it's not about content jumping! I have a navbar and a sidebar which both have absolute position. after user scrolls 100 pixels I change both of them

Solution 1:

Causes

Scrolling can generate scroll events quickly and handlers may need to either throttle scroll events to some extent (e.g. perform code action after scrolling has stopped) or be fairly lightweight functions that can execute quickly.

In addition scroll event handling is not synchronized with page update: if the mouse wheel initiates downward scrolling, scrolling can continue after the wheel is released (and similarly with touch event scrolling). The browser can scroll below a top position of 100px before scroll event handling has had a chance to catch up and change the positioning.

The result is the header jumps down from being partially off-screen to occupy a fixed position at top of screen. The faster the scroll action (or the busier the browser is) the more likely it is that jumping will be noticeable.

A secondary effect in desktop browsing is that when the side bar panel scrolls upwards past top of screen and moves down again, a visible patch of white screen "flashes" momentarily below the side bar before fixed positioning takes effect.

Experimental Remedies

Flashing of the side bar can be reduced but not necessarily fully eliminated, by increasing the height of the container. Changing the height to 150% with visible overflow met with some success:

.side-bar {
position: absolute;
height: 150%;
... /* more declarations */

This may or may not conflict with application requirements.

Some mitigation of navbar jumping can be achieved by using requestAnimationFrame call backs to monitor scrollTop values and change positioning as necessary. This does not use scroll event handling as such:

$(document).ready(function() {
    $(window).resize(function() {
        if( $(window).width() > 850) {
            $('.navbar').css('display', 'block');   
        } else {
            $('.navbar').css('display', 'none');
        }
    });
    scrollTo(0, 0);
    var num = 100;
    var bAbsolute = true;
    functioncheckScroll() {
        var newTop = $(window).scrollTop();
        if( bAbsolute && newTop >= num) {
             $('.navbar').css('position', 'fixed');
            $('.navbar').css('top', '0');
            $('.side-bar').css('position', 'fixed');            
            $('.side-bar').css('top', '0');
            bAbsolute = false;
        }
        if( !bAbsolute && newTop < num) {
            $('.navbar').css('position', 'absolute');
             $('.side-bar').css('position', 'absolute');
             $('.navbar').css('top', '100px');
             $('.side-bar').css('top', '100px');
            bAbsolute = true;
        }
        requestAnimationFrame( checkScroll);

    } 
    requestAnimationFrame( checkScroll)
});

This code showed an improvement in jump reduction but was not perfect. It is not particularly a JQuery solution and calls requestAnimationFrame directly.

One option, of course, is to do nothing given browser timing constraints.


Update

This MDN guide for Scroll linked effects explains the root cause problem better than I was able to:

most browsers now support some sort of asynchronous scrolling .... the visual scroll position is updated in the compositor thread and is visible to the user before the scroll event is updated in the DOM and fired on the main thread ... This can cause the effect to be laggy, janky, or jittery — in short, something we want to avoid.

So the absolutely positioned elements can scroll off screen (to some extent) before scroll handlers are notified of a new scroll position.

The solution going forward is to use sticky positioning (see the scroll effects guide above or the CSS position guide. However position:sticky swaps between relative and fixed position so the HTML would need redesigning to accommodate this.

Sticky positioning is also leading edge technology at January 2018, and not yet recommended for production use on MDN. A web search for "JQuery support sticky position" revealed a choice of JQuery plugin support.

Recommendation

Potentially the best-case compromise may be to redesign the HTML to use sticky positioning and include a JQuery plugin that uses native support when available or a polyfill when not - site visitors with supporting browsers will get the best experience, those with older browsers will get functional support.

Post a Comment for "Unexpected Jump While Changing Position From Absolute To Fixed, Why?"