Parallax section initial background-position is not consistent with when the page is scrolled

StackOverflow https://stackoverflow.com/questions/23452318

  •  15-07-2023
  •  | 
  •  

Question

I've spent my entire day trying to create a Parallax section that works fine no matter where it's placed on the page, but every change I make to the code solves one problem and creates another. Here is my code so far:

(function( $ ) {
  "use strict";
    $('.parallax-section').each(function(){
        var $el = $(this),
            speed = 0.4,
            elOffset = $el.offset().top;

        $(window).scroll(function() {
          var diff = $(window).scrollTop() - elOffset;
          var yPos = -(diff*speed);

          var coords = '50% '+ yPos + 'px';
          $el.css({ backgroundPosition: coords });
        });
    });
}(jQuery));

The Css:

.parallax-section{
    background-position: 50% auto;
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-image: url('http://lorempixel.com/1400/700')
}

Here is a jsfiddle on this. Here you'll see that the first parallax section jumps to the background position value set by the above code, while the second one down the page works fine.

I understand that this happens because the code above assumes that elOffset value is larger than scrollTop, which is not the case for the first one.

Can someone please tell me how I can I set initial value of the background-position, so that this jump doesn't happen.

Thanks.

Update: Added content above the first Parallax section to show the jump correctly.

Was it helpful?

Solution

All you really need to do to make sure that there is no jump, is to make sure you set the initial value the same way that you set it on scroll.

The best way to do this is to move your code into a function, outside of the scroll handler, and then call that function in the scroll handler instead. Then, you can also call that function any other time you might want.. like on page load.

Here's what I changed your code to:

(function ($) {
    "use strict";

    $('.parallax-section').each(function () {

        var $el = $(this);

        $(window).scroll(function () {
            updateBackground($el);
        });
        updateBackground($el);
    });

}(jQuery));

var speed = 0.4;

function updateBackground($el) {

    var diff = $(window).scrollTop() - $el.offset().top;
    var yPos = -(diff * speed);

    var coords = '50% ' + yPos + 'px';

    $el.css({
        backgroundPosition: coords
    });
}

See Demo

Basically, the updateBackground() function does all the work that the scroll event was doing before. Now, on scroll, I simply call that function, and pass it the information that it needs.

Beneath that, I also immediately call the function, this way it will run on page load as well.

(note that I also moved the speed variable outside of the .each(), both so that it can be referenced more easily by the new function, and also because it doesn't need to get set over and over again.. it's always the same, we only really need to declare it once.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top