IntroductionOne of the most common questions around animation performance is whether JS-based animations are slower than CSS-based ones. Should we always strive to use CSS transitions, or is it OK to use JavaScript animation libraries? There’s a surprising amount of nuance to this question, and I think that the conventional wisdom isn’t quite right. In this post, we’re going to dig into this question and see the differences for ourselves! Link to this headingComparing CSS keyframes to JavaScript loops Let’s suppose we’re building the following animation: We can wire this up with a CSS keyframe, like this: Copy to clipboard@keyframes bounce { to { transform: translateX(calc(var(--bounce-magnitude) * -1)); } } .ball { --bounce-magnitude: 200px; animation: bounce 1000ms infinite alternate; } (I’m using a CSS transform for this animation because it produces the smoothest motion. In cases where the container size is dynamic, we would need to calculate and apply --bounce-magnitude in JS.) Alternatively, we could implement this animation using JavaScript! Before we consider JS libraries like GSAP or Motion, let’s start with a plain JS version: Copy to clipboardconst startTime = performance.now(); const ball = document.querySelector('.ball'); function animate() { const elapsedTime = performance.now() - startTime; // ✂️ Calculate `x` based on the amount of time that has passed. ball.style.transform = `translateX(${x}px)`; window.requestAnimationFrame(animate); } This code uses requestAnimationFrame to run the animate function on every frame (60 times per second on most displays). I’ve cut out the main logic to calculate x since it’s a bit complicated and not relevant for the topic at hand, but you can see the full code(opens in new tab) if you’re curious. Here’s the question: which approach do you think runs more smoothly? I think for most of us, our intuitions would tell us that the CSS version is more performant. And our intuition is correct, but maybe not for the reasons ...
First seen: 2026-05-27 20:58
Last seen: 2026-05-28 12:10