Parallax animation running well on Chrome but slow on Safari
parallaxElements = [];

// Push elements to array
s.parallaxElements.each(function (i) {
  var i = {
    element: $(this),
    ratio: $(this).data('parallax-ratio'),
    offset: $(this).closest('.parallax-section').offset().top - 60,
    current: 0
  };

  parallaxElements.push(i);
});


This looks like transforming one array to another on a 1:1 basis. This is best done with array.map. Also, you should cache the result of $(this) so that you don't call it repeatedly. Additionally, this inside a jquery.each is the current item, which should be the same as the first argument in array.map's callback.

var parallaxElements = s.parallaxElements.get().map(element =&gt; {
  const wrappedElement = $(element);

  return {
    element: wrappedElement,
    ratio: wrappedElement.data('parallax-ratio'),
    offset: wrappedElement.closest('.parallax-section').offset().top - 60,
    current: 0
  };
});


Now for your animation, I suggest you avoid using requestAnimationFrame in this case. It will still be running even when no position changes are taking effect, eating up cycles.

Since your parallax effect only takes place only when scroll position has changed, I suggest you listen for the window's scroll event and do changes when scrolled. As for the movement animation, use CSS transitions.

$(window).scroll(event =&gt; {
  // Update element positions using transform translate
});

.parallax-element{
  transition: transform 0.2s;
}