JavaScript Video Tutorial: Parallax Scroll Effect


In this tutorial we will see how to create a parallax effect in JavaScript when scrolling the page. The objective is to make sure that different elements of the page scroll faster or slower than the scroll to give an effect of perspective / depth.

What approach?

To create this effect, the idea is to apply a translation on the element according to the user's scrolling level. To calculate the translation to apply, we will calculate the position of the element in relation to the center of the screen.

We have 2 possibilities to do this calculation:

  • Use the getBoundingClientRect () which provides information on the size and position of the element in relation to the screen.
  • The offsetTop which makes it possible to obtain the position of the element relative to the nearest positioned container.

The offsetTop has the advantage of not being affected by the transformation which can simplify the calculation. The other advantage is that the offsetTop can be calculated and saved upstream (if the structure of your page does not change). We will just be careful to calculate this offsetTop recursively to get the position relative to the top of the page.

/ **
 * Calculate the position of the element relative to the top of the page
 * @param {HTMLElement} element
 * @return {number}
 * /
function offsetTop (element, acc = 0) {
  if (element.offsetParent) {
    return offsetTop (element.offsetParent, acc + element.offsetTop);
  }
  return acc + element.offsetTop;
}

This value can then be used to calculate the difference from the center of the screen.

const elementY = offsetTop (this.element) + this.element.offsetHeight / 2;
const screenY = window.scrollY + window.innerHeight / 2;
const diffY = this.elementY - screenY;

Finally, this difference must be applied to the translateY to slow down or accelerate the feeling of scrolling.

element.style.setProperty ("transform", `translateY ($ {diffY * -1 * ratio} px)`);

This calculation will be repeated when the user scrolls.

Optimization

We will be careful to optimize the performance of our animation in order to avoid slowing down the scrolling.

  • We encompass our transformation in a window.requestAnimationFrame so as not to do any calculations when the browser is not drawing.
  • We use the IntersectionObserver to detect when the element becomes visible on the screen and only start the behavior then.