Jan Zoutendijk Jan Zoutendijk - 2 months ago 39
jQuery Question

Jquery animate css on scrolling causes jitter

EDIT: The problem was using javascript animations in stead of CSS transitions. The codepen now shows a working example where JS is only used to translate the elements and CSS is used to animate it!

I'm trying to achieve a certain effect which I've seen at this website: https://draft.co.jp/en/projects/page/geechs.

They use a fixed positioned main section within a body element that has a fixed height (to generate the scrollbar). After scrolling they translate all elements within the main element in ratio with the $(window).scrollTop(). They use a animation that smooths this effect.

I've been trying to recreate this effect, but my code will generate a jittered experience after a few scrolls. (see https://codepen.io/blauwhelm/pen/LRorNA for an example).

It seems that generating a lot of animations (I'm using transition via a jquery plugin in this example to animate the translate property) is causing this problem. I've already tried using throttling to limit the amount of triggers, but this doesn't fix the problem.

My javascript:

$(document).ready(function() {

var $mainElement = $('.main__element');

function smoothScroller(e) {
var scrollTop = $(window).scrollTop();
console.log('scroll trigger');
$mainElement.stop(true, false).transition({y: -scrollTop}, 3000, "cubic-bezier(.19,0.88,0,.99)", function() {
console.log('end animation');

$(window).bind('scroll', smoothScroller);

Somehow there are a lot more 'end animation' messages than 'scroll trigger', which I also don't understand.

Anybody any ideas how I can fix the jittery animations?



They are using Greensock's GSAP heavily for this, which is a great lib, but more of an enterprise solution and a decent learning curve.

A good place to start would be to check out requestAnimationFrame and a throttling method (i used lodash for this example).

Using translateY (or X, or 3d) helps too instead of using top

Here's a JSBin demo with HTML/CSS/JS, but here's the relevant bit:


var ticking = false,
    item = document.querySelectorAll('.item');

// RAF
function update() {
  ticking = false; 
  item[0].style.transform = 'translateY('+window.scrollY+'px)';

function onScroll() {
  ticking = ticking || requestAnimationFrame(update);

window.addEventListener('scroll', onScroll, false);

// Scroll Throttle
function throttled_version() {
  item[1].style.transform = 'translateY('+window.scrollY+'px)';

window.addEventListener('scroll', _.throttle(throttled_version, 16), false);

Giving the CSS a transition can help the fluidity as well. Just 50ms in this case since it fires repeatedly. It kind of simulates a velocity/momentum effect