Justin Cefai
Justin Cefai

Reputation: 151

Prevent divs from "jumping" on scroll animation

I'm trying to animate two divs to slide into and out of the screen on scroll. Scroll down and they move outward until they are out of view. Scroll up and they slide back into view and stop at their original position specified in the CSS (I've used keyframes to achieve this on the page load). The issue is that the divs jump roughly 500px from their original position as soon as the scroll movement is activated - i.e. the left div will jump over to the right side, then it will move over to the original specified CSS position instead of starting at that position and moving off screen. As it stands, I only have the behavior set up for the left element as an example.

Unfortunately I'm unable to achieve any scrolling behavior in Codepen, and I don't want to push this live to my site with errors present. Regardless, here is the code along with a link. Any suggestions to the wording of the question as well as a solution to the issue are welcome and appreciated.

Here is a video of the issue. - https://www.youtube.com/watch?v=G2dAX2fPPN4&feature=youtu.be

https://codepen.io/anon/pen/axpMwZ

$(document).ready(function() {
  var $horizontal = $('.about-left');

  $(window).scroll(function() {
    var s = $(this).scrollTop(),
      d = $(document).height(),
      c = $(this).height();

    scrollPercent = (s / (d - c) * 18);

    var position = (scrollPercent * ($(document).width() - $horizontal.width()));

    $horizontal.css({
      'right': position
    });
  });
});
.main {
  height: 300vh; // maximized to illustrate scroll
  width: auto;
}

.about-left {
  position: absolute;
  top: 22%;
  left: 18%;
  font-size: 300px;
  color: #15ad93;
  text-shadow: 0px 1px 3px black;
  animation: 1s ease-out 0s 1 slideInFromLeft;
}

.about-right {
  position: absolute;
  top: 22%;
  right: 18%;
  font-size: 300px;
  color: #15ad93;
  text-shadow: 0px 1px 3px black;
  animation: 1s ease-out 0s 1 slideInFromRight;
}

@keyframes slideInFromLeft {
  0% {
    transform: translateX(-200%);
    opacity: 0;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}

@keyframes slideInFromRight {
  0% {
    transform: translateX(200%);
    opacity: 0;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">

  <div class="about-left">[]</div>

  <div class="about-right">[]</div>

</div>

Upvotes: 0

Views: 2219

Answers (2)

Don&#39;t Panic
Don&#39;t Panic

Reputation: 14520

Why your Codepen isn't showing scrolling

1) Absolute positioning requires a parent element with a relative position. Probably while simplifying your code for this question and Codepen, your .main div lost that. I've added it back.

2) When that still didn't get things working, I checked the dev console and noticed an error about <script> tags. Your Codepen includes those in the JS panel, turns out they are not required, and actually cause a problem. I removed them.

Why your animation is jumping

In short - it is just a math problem. Your .about-left styling starts at left: 18%;. On scroll that is overridden with the inline style using right: <something>, where <something> changes with scroll position. The very first value of that <something> is drastically different than the initial left: 18%; position, so boom the element jumps across the screen. I didn't try to puzzle through the details of your scrolling math to work out why, as there's a simpler fix.

The simplest option is to use a consistent positioning mechanism initially and on scroll. For the initial position, left: 18%; can alternatively be expressed as:

right: calc(82% - 200px);

Just using 82% positions the right side of the box containing the element at 82% from the right hand side of the page, but we actually want the left side of the box there, so we have to subtract the width of that box. In your Codepen that's 200px, though that probably depends on your final styling and might be different in your real code (eg your video shows a nice curly brace rather than the square ones in the Codepen). You'll have to adjust as necessary.

Next, I updated your JS scrolling code to change position starting from that same initial position:

$horizontal.css({
    'right': 'calc(82% - 200px + ' + position + 'px)'
});

As long as your very first value of position is relatively small, the first move will be only a small distance from the starting point.

Note you have to use quotes around the calc(), and unquote the position JS variable.

Updated, working Codepen. The animation is pretty fast, I mean it moves off screen quickly and in pretty large jumps, though of course you can tune the increment value by adjusting your math (watch the console for the logged position values).

Upvotes: 1

m ba
m ba

Reputation: 134

Your css:

.about-left {
  ...
  left: 18%;
  ...
}

Your js:

$horizontal.css({
    'right': position
});

Try to use in both "left" or in both "right".

or add to .about-left class "text-align: right;"

Upvotes: 0

Related Questions