JS scroll listener for animation causing page jump during mobile scroll

I have written some custom code for an ‘animation’. The animation counts for 0 to a certain number as specified in the function. This works fine on desktop but on my android phone it is causing the page to jump back up a little bit when you scroll down to this section of the page. You also cannot see the animation. It seems like it:

  • Triggers the animation
  • Jumps back up the back the page a little as the animation runs
  • User scrolls down again and it shows the updated numbers after the count up animation is done

This is the page I have the problem on: https://quedamoslanguages.com/ so you can see the bug here.

The section to look at is the ‘YEARS EXPERIENCE’, ‘STUDENTS’ etc. It is 2/3 down the page.

This is the custom function

import { runOnScroll, throttle } from './common.js';

function doCountAnimation(element, targetNumber, duration = 1000) {
    if (!element) {
        console.error(`Element with selector '${elementSelector}' not found.`);
        return;
    }
    const startTime = performance.now();
    function updateCount(currentTime) {
        const elapsedTime = currentTime - startTime;
        const progress = Math.min(elapsedTime / duration, 1);
        const currentNumber = Math.floor(progress * targetNumber);
        element.textContent = currentNumber;
        if (progress < 1) {
            requestAnimationFrame(updateCount); // requestAnimationFrame() is build in browser function
        }
    }
    requestAnimationFrame(updateCount);
}


function triggerCountAnimation(element){
    doCountAnimation(element.querySelector('div.wp-block-group:nth-child(1) p:nth-child(1)'), 31);
    doCountAnimation(element.querySelector('div.wp-block-group:nth-child(2) p:nth-child(1)'), 7);
    doCountAnimation(element.querySelector('div.wp-block-group:nth-child(3) p:nth-child(1)'), 14);
    doCountAnimation(element.querySelector('.wp-block-group:nth-child(4) p:nth-child(1)'), 1000);
    window.removeEventListener('scroll', throttledScrollHandler);
}

const throttledScrollHandler = throttle(() => runOnScroll('.big-numbers-container-home .wp-block-group', triggerCountAnimation), 300);

// Throttling the function with an anonymous wrapper to pass the selector
window.addEventListener('scroll', throttledScrollHandler, { passive: true });


And these are the 2 functions which I am importing

export const throttle = (fn, delay) => {
    // Set up the throttlerconst throttle = (fn, delay) => {
    let time = Date.now();
    return () => {
        if ((time + delay - Date.now()) <= 0) {
            fn();
            time = Date.now();
        }
    };
}

export function runOnScroll(selector, animationFn) {
    const element = document.querySelector(selector);
    if (element) {
        if(isInViewport(element)){
            animationFn(element)
        }
    } else {
        console.log('Element not found for selector:', selector);
    }
}

As you can see I have throttled the function so that the scroll function does not run all the time in order to improve performance.

I did try taking the throttle function out so did this –
window.addEventListener(‘scroll’, () => runOnScroll(‘.big-numbers-container-home .wp-block-group’, triggerCountAnimation), { passive: true });

But was still seeing the same issue. Of course I just want the page to scroll from top to bottom without jumping around anywhere in the process.

Any ideas would be much appreciated !