DEV Community

Nikita Dmitriev
Nikita Dmitriev

Posted on • Edited on

The other side of using requestAnimationFrame

Backstory

I was looking through the Vue source code and came across this:
vue.js

function nextFrame(cb) {
      requestAnimationFrame(() => {
          requestAnimationFrame(cb);
      });
  }
Enter fullscreen mode Exit fullscreen mode

It turns out that Vue uses the requestAnimationFrame function twice when adding and removing classes during transitions.

What's the purpose of double requestAnimationFrame?

I spent a considerable amount of time trying to understand the reason behind this approach. While I may not have fully grasped its intricacies, here's what I discovered.

Consider this example:

index.html

<button class="btn btn-primary" id="btnStart">Start</button>
<div class="alert alert-success move-animation" id="target">Hello world</div>
Enter fullscreen mode Exit fullscreen mode

style.css

.move-animation {
    animation: move 2s linear;
}

@keyframes move {
    0% {
        transform: translateX(0);
    }

    50% {
        transform: translateX(100px);
    }

    100% {
        transform: translateX(0);
    }
}

.testClass {
    color: red;
}
Enter fullscreen mode Exit fullscreen mode

script.js

var element = document.getElementById('target');
var btnStart = document.getElementById('btnStart');

function raf(fn) {
    window.requestAnimationFrame(function () {
        window.requestAnimationFrame(function () {
            fn();
        });
    });
}

function addClass() {
    element.classList.add('testClass');
}

btnStart.addEventListener('click', () => {
    element.classList.remove('testClass');
    raf(addClass);
});
Enter fullscreen mode Exit fullscreen mode

If you decide to test this code, you may not notice a significant difference between raf(addClass); and simply window.requestAnimationFrame(addClass);. However, in more complex projects, when a user on a Macintosh device visits your site, they may experience flickering and potentially incorrect rendering of elements during animations. While I cannot provide concrete evidence, rest assured that using the double requestAnimationFrame method does not introduce more performance overhead than window.requestAnimationFrame(addClass);. There may be a slight difference, but after extensive browser testing, I did not observe any additional burden.

Summary

Employing double requestAnimationFrame ensures that the addClass function executes successfully during the next two consecutive animation steps, resulting in smoother and synchronized animations without undesirable effects.

P.S. Whether or not to utilize this approach is a personal choice. I encourage you to share your thoughts in the comments and engage in discussions regarding this matter. Personally, I find value in using this method, particularly when working with the DOM through JavaScript and dealing with elements that have CSS-defined animations.

Top comments (0)