JavaScript Animations and Transitions

Animations and transitions help keep web experiences dynamic and eye-catching in modern web design. And well, not all animation techniques are equally good. Some techniques may degrade performance by loading the main thread, especially on under-resourced devices. And so, let’s delve into this guide to ensure we’re creatively wielding both JS animations and CSS transitions with very little main-thread work for slick and elegant looks.

 

Animation Performance Overview

Before going further into animation techniques, let us understand the situations which make some animations demand heavy performances. The major aspects are:

Main-thread work: Computation on the main thread may make an animation lag. Consider avoiding the main thread for performance purposes.
Repaints and reflows: Some CSS properties will force the browser to recalculate the layout (reflow) or redraw (repaint). Minimizing these will ensure smooth animation running.
GPU acceleration: Uses the GPU to accelerate some processes and take that workload off the CPU, thus creating faster and smoother animations.

 

When Should You Prefer CSS Transitions and Animations to JavaScript?

CSS animations or transitions are best for simple animating systems such as hover and fades. They are lighter and browsers tend to optimize these better than JavaScript animation, which allows smoother GPU execution.

Some examples of CSS animations include:
Opacity and transform changes (scaling, rotation, translation, and the like): These are GPU-accelerated and avoid triggering layout recalculations.
Hover effects: Quick transitions on hover are very lightweight and should probably be implemented with CSS.

JavaScript will come in handy with the following:

– When animations are too complex or interactive.
– When you need to control on the fly the order in which animations occur or want staggered animations.
– When the animation needs to be synced with user input such as scrolling or mouse movement.

Techniques for Performant JavaScript Animations

When using JavaScript for animations, performance optimization is key. Here are techniques to help ensure smooth, performant animations.

a. Use `requestAnimationFrame` for JavaScript Animations

Using `setTimeout` or `setInterval` to run animations can cause lag, as these methods don’t synchronize with the browser’s refresh rate. Instead, use `requestAnimationFrame`, which tells the browser to perform an animation just before the next repaint, ensuring it aligns with the screen’s refresh rate.

function animate(element, timestamp) {
// Perform animation work here
element.style.transform = `translateX(${Math.sin(timestamp / 100) * 50}px)`;

// Continue the animation loop
requestAnimationFrame((timestamp) => animate(element, timestamp));
}

// Start the animation
const element = document.querySelector(‘.animated’);
requestAnimationFrame((timestamp) => animate(element, timestamp));

b. Minimize any Layout Thrashing

Animations that read and write into the DOM set off layout thrashing, where the browser tries repeatedly to calculate layout, débouching into slow performance. To avert this, ensure that reads and writes always occur as a batch.

For instance, employ a library like FastDOM to schedule reads and writes into the DOM so layout recalculations occur less often.

import fastdom from 'fastdom';

fastdom.measure(() => {
const height = element.offsetHeight;
});
fastdom.mutate(() => {
element.style.height = `${height}px`;
});

c. Web Animations API

The Web Animations API carries out animation directly on the browser, thus allowing efficient animations with less overhead from JavaScript. It suits intricate animations and offers a bit more control than CSS keyframes.

const element = document.querySelector('.animated');
element.animate(
[
{ transform: 'translateX(0px)' },
{ transform: 'translateX(100px)' }
],
{
duration: 1000,
iterations: Infinity
}
);

Optimizing CSS Animations

CSS animations are more performant than JavaScript in many cases, but only if you use them efficiently. Here are key techniques for optimizing CSS animations.

#

a. Use `transform` and `opacity` Properties

Properties like `transform` and `opacity` can animate without causing a reflow or repaint, as they don’t change the document’s layout. This allows the browser to move these animations to the GPU.

.element {
transition: transform 0.3s ease, opacity 0.3s ease;
}

.element:hover {
transform: scale(1.05);
opacity: 0.8;
}

b. Refrain From Animating Properties Affecting Layout

Avoid `width`, `height`, `margin`, or `padding` in animations, since they cause reflows. Instead, use `transform: scale` for resizing and `opacity` for fading effects.

c. Keyframe Animation Optimizations

Keyframe animations should be kept with a minimal number of frames. The shorter the keyframes, the less computation required for them, and thus they stay lightweight.

@keyframes slide {
from {
transform: translateX(0);
}
to {
transform: translateX(100px);
}
}

Combining JavaScript and CSS for Interactive Animations

For more complex interactions, you have the option of combining JavaScript and CSS animations so that each language does what it does best. JavaScript can handle task logic, while CSS will handle rendering.

In, say, drag-and-drop interaction, JavaScript is used to track the position of the dragged item and update CSS transforms accordingly:

let startX, startY, offsetX = 0, offsetY = 0;
const element = document.querySelector('.draggable');

element.addEventListener(‘mousedown’, (event) => {
startX = event.clientX – offsetX;
startY = event.clientY – offsetY;

window.addEventListener(‘mousemove’, onMouseMove);
window.addEventListener(‘mouseup’, onMouseUp);
});

function onMouseMove(event) {
offsetX = event.clientX – startX;
offsetY = event.clientY – startY;

element.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
}

function onMouseUp() {
window.removeEventListener(‘mousemove’, onMouseMove);
window.removeEventListener(‘mouseup’, onMouseUp);
}

GPU Acceleration for the Fancy Animations

Certain animations, when possible, are actually offloaded by the browser onto the GPU, which can wonderfully perform certain graphical tasks quickly. Here are some tricks to keep the GPU acceleration on:

– The rendering can be forced by passing in a `translateZ(0)` or `translate3d(0, 0, 0)`. This usually speeds things up, but seldom use it because making too many GPU layers just drains the device.

.animated {
transform: translateZ(0);
}

Avoid heavy GPU layers: Too many GPU layers can mean bad performance- so channel GPU acceleration in only a few elements.

Tips to Debug Animation Performance

Use the following to judge your animations and improve:

Chrome DevTools Performance Panel: Record an animation and inspect main-thread blocking in the Timeline.
DevTools’ Layers panel: View layers generated by your animation and catch any unintended GPU usage.
FPS meter: Keep track of the frame rate during an animation, making sure it holds steady at 60fps.

Performer animations and transitions in JavaScript and CSS shall lay the groundwork for a functional next generation of interactive websites. By adhering to these suggestions-giving CSS transitions to simpler animations, putting JavaScript animations under requestAnimationFrame for smoother performing, and optimizing GPU use-an animator becomes an actor on screen, with all the beauty and glory but none of the pain of production delays.