Web Animations API, a powerful browser-native tool for creating smooth and dynamic animations using pure JavaScript, without relying on CSS or third-party libraries. Compared to CSS animations, the Web Animations API offers greater flexibility, enabling dynamic control like pausing, reversing, and seamless integration with JavaScript logic.
What is the Web Animations API?
The Web Animations API is a native JavaScript API based on W3C standards, designed for creating and controlling animations. It combines the smoothness of CSS animations with the flexibility of JavaScript, allowing precise manipulation of element properties like position, color, and opacity. Key features include:
- Native Support: No external libraries needed, supported by modern browsers (Chrome, Firefox, Safari, etc.).
- Fine-Grained Control: Dynamically modify animation parameters, pause, play, reverse, or adjust speed.
- High Performance: Runs off the main thread (compositor thread), as smooth as CSS animations.
- CSS/JavaScript Integration: Manipulates CSS properties and integrates with events and data binding.
- Composability: Supports multi-segment animations, timelines, sequential, and parallel animations.
We’ll start with basic animations and progress to complex scenarios, integrating with React and Vue for practical applications.
Environment Setup
The Web Animations API is built into browsers, requiring no libraries, but we need a simple development environment. Create an HTML project:
mkdir web-animations-demo
cd web-animations-demo
touch index.html
Install a local server (e.g., live-server):
npm install -g live-server
Directory structure:
web-animations-demo/
├── index.html
├── style.css
├── script.js
Run live-server and visit localhost:8080. We’ll use plain HTML/CSS/JS for animations, later adding React and Vue.
Basic Animation: Movement and Scaling
The core of the Web Animations API is Element.animate(), which takes keyframes and options. Create a simple movement animation.
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Web Animations API Demo</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="box"></div>
<script src="script.js"></script>
</body>
</html>
style.css:
.box {
width: 100px;
height: 100px;
background: #007bff;
position: absolute;
top: 50px;
left: 50px;
}
script.js:
const box = document.querySelector('.box');
box.animate(
[
{ transform: 'translateX(0)' },
{ transform: 'translateX(300px)' }
],
{
duration: 1000,
easing: 'ease-in-out',
iterations: Infinity,
direction: 'alternate'
}
);
Run live-server. A blue box moves back and forth along the X-axis. Code breakdown:
-
animate()takes two arguments: an array of keyframes (like CSS keyframes) and a configuration object. - Keyframes define animation states, with
transform: translateXcontrolling X-axis movement. - Options:
-
duration: Animation length in milliseconds. -
easing: Easing function,ease-in-outfor smooth transitions. -
iterations: Number of loops,Infinityfor infinite looping. -
direction:alternatefor back-and-forth playback.
-
Controlling Animations
animate() returns an Animation object, allowing pause, play, or reverse. Update script.js:
const box = document.querySelector('.box');
const animation = box.animate(
[
{ transform: 'translateX(0) scale(1)' },
{ transform: 'translateX(300px) scale(1.5)' }
],
{
duration: 1000,
easing: 'ease-in-out',
iterations: Infinity,
direction: 'alternate'
}
);
document.addEventListener('click', () => {
if (animation.playState === 'running') {
animation.pause();
} else {
animation.play();
}
});
Click the page to pause/resume the animation, which now includes scaling. Animation object methods:
-
play(): Starts the animation. -
pause(): Pauses the animation. -
playState: Current state (running,paused, etc.). -
reverse(): Reverses playback.
Multi-Property Animation
The Web Animations API supports animating multiple properties, like color, opacity, and size. Update script.js:
const box = document.querySelector('.box');
const animation = box.animate(
[
{
transform: 'translateX(0) scale(1)',
backgroundColor: '#007bff',
opacity: 1
},
{
transform: 'translateX(300px) scale(1.5)',
backgroundColor: '#ff5733',
opacity: 0.5
}
],
{
duration: 1500,
easing: 'ease-in-out',
iterations: Infinity,
direction: 'alternate'
}
);
The box moves, changes from blue to orange, and fades opacity from 1 to 0.5. Keyframes support any CSS property (in camelCase, e.g., backgroundColor).
Dynamic Keyframes
Generate keyframes dynamically with JavaScript. Update script.js:
const box = document.querySelector('.box');
let distance = 300;
const keyframes = [
{ transform: `translateX(0) scale(1)`, backgroundColor: '#007bff' },
{ transform: `translateX(${distance}px) scale(1.5)`, backgroundColor: '#ff5733' }
];
const animation = box.animate(keyframes, {
duration: 1500,
easing: 'ease-in-out',
iterations: Infinity,
direction: 'alternate'
});
document.addEventListener('keydown', e => {
if (e.key === 'ArrowRight') {
distance += 50;
const newKeyframes = [
{ transform: `translateX(0) scale(1)`, backgroundColor: '#007bff' },
{ transform: `translateX(${distance}px) scale(1.5)`, backgroundColor: '#ff5733' }
];
box.animate(newKeyframes, {
duration: 1500,
easing: 'ease-in-out',
iterations: Infinity,
direction: 'alternate'
});
}
});
Press the right arrow key to increase the movement distance. animate() replaces the old animation with new dynamically generated keyframes, showcasing flexibility.
Sequential and Parallel Animations
The Web Animations API supports sequential and parallel animations. Create a sequential animation.
Update index.html:
<div class="box"></div>
<div class="box" style="top: 200px;"></div>
Update script.js:
const boxes = document.querySelectorAll('.box');
boxes.forEach((box, index) => {
box.animate(
[
{ transform: 'translateX(0)' },
{ transform: 'translateX(300px)' }
],
{
duration: 1000,
delay: index * 500,
easing: 'ease-in-out',
iterations: Infinity,
direction: 'alternate'
}
);
});
Two boxes move sequentially, with the second starting 500ms later due to delay: index * 500. Remove delay for parallel animations.
Timeline Control
Use Animation’s startTime and currentTime for timeline control. Update script.js:
const box = document.querySelector('.box');
const animation = box.animate(
[
{ transform: 'translateX(0)', opacity: 1 },
{ transform: 'translateX(300px)', opacity: 0.5 }
],
{
duration: 2000,
easing: 'ease-in-out',
iterations: 1
}
);
document.addEventListener('click', () => {
animation.currentTime = 0; // Reset to start
animation.play();
});
Click to restart the animation. currentTime sets the animation progress in milliseconds.
Animation Events
The Web Animations API supports event listeners for events like completion or cancellation. Update script.js:
const box = document.querySelector('.box');
const animation = box.animate(
[
{ transform: 'translateX(0)', opacity: 1 },
{ transform: 'translateX(300px)', opacity: 0.5 }
],
{
duration: 1000,
iterations: 1
}
);
animation.onfinish = () => {
console.log('Animation finished!');
box.style.transform = 'translateX(300px)';
box.style.opacity = '0.5';
};
animation.oncancel = () => {
console.log('Animation cancelled!');
};
document.addEventListener('click', () => {
if (animation.playState === 'running') {
animation.cancel();
} else {
animation.play();
}
});
The animation logs “Animation finished!” on completion and “Animation cancelled!” on cancellation. onfinish applies final styles to prevent flickering.
Using in React
Use the Web Animations API in React. Create a React project:
npx create-react-app react-animations
cd react-animations
Update src/App.js:
import { useRef, useEffect } from 'react';
import './App.css';
function App() {
const boxRef = useRef(null);
useEffect(() => {
const box = boxRef.current;
const animation = box.animate(
[
{ transform: 'translateX(0)', backgroundColor: '#007bff' },
{ transform: 'translateX(300px)', backgroundColor: '#ff5733' }
],
{
duration: 1000,
easing: 'ease-in-out',
iterations: Infinity,
direction: 'alternate'
}
);
return () => animation.cancel(); // Cleanup
}, []);
return (
<div style={{ padding: 20 }}>
<h1>React Animation</h1>
<div ref={boxRef} className="box"></div>
</div>
);
}
export default App;
src/App.css:
.box {
width: 100px;
height: 100px;
background: #007bff;
position: absolute;
top: 50px;
}
Run npm start. The box moves and changes color. useRef accesses the DOM element, useEffect runs the animation, and cleanup cancels it to prevent memory leaks.
Dynamic Control
Add interactive control:
import { useRef, useEffect, useState } from 'react';
import './App.css';
function App() {
const boxRef = useRef(null);
const [isPlaying, setIsPlaying] = useState(true);
useEffect(() => {
const box = boxRef.current;
const animation = box.animate(
[
{ transform: 'translateX(0)', backgroundColor: '#007bff' },
{ transform: 'translateX(300px)', backgroundColor: '#ff5733' }
],
{
duration: 1000,
easing: 'ease-in-out',
iterations: Infinity,
direction: 'alternate'
}
);
if (!isPlaying) animation.pause();
return () => animation.cancel();
}, [isPlaying]);
return (
<div style={{ padding: 20 }}>
<h1>React Animation</h1>
<div ref={boxRef} className="box"></div>
<button onClick={() => setIsPlaying(!isPlaying)}>
{isPlaying ? 'Pause' : 'Play'}
</button>
</div>
);
}
export default App;
Click the button to toggle the animation. useEffect updates based on isPlaying.
Using in Vue
Use the Web Animations API in Vue. Create a Vue project:
vue create vue-animations
cd vue-animations
Update src/App.vue:
<template>
<div style="padding: 20px;">
<h1>Vue Animation</h1>
<div ref="box" class="box"></div>
<button @click="toggleAnimation">{{ isPlaying ? 'Pause' : 'Play' }}</button>
</div>
</template>
<script>
export default {
data() {
return {
isPlaying: true,
animation: null
};
},
mounted() {
this.animation = this.$refs.box.animate(
[
{ transform: 'translateX(0)', backgroundColor: '#007bff' },
{ transform: 'translateX(300px)', backgroundColor: '#ff5733' }
],
{
duration: 1000,
easing: 'ease-in-out',
iterations: Infinity,
direction: 'alternate'
}
);
},
methods: {
toggleAnimation() {
this.isPlaying = !this.isPlaying;
if (this.isPlaying) {
this.animation.play();
} else {
this.animation.pause();
}
}
},
beforeUnmount() {
this.animation.cancel();
}
};
</script>
<style>
.box {
width: 100px;
height: 100px;
background: #007bff;
position: absolute;
top: 50px;
}
</style>
Run npm run serve. The box animates, and clicking the button pauses/plays it. ref accesses the DOM, and beforeUnmount cleans up the animation.
Complex Scenario: Interactive Animation
Create a draggable animation with the Web Animations API.
Update index.html:
<div class="box" id="draggable"></div>
Update style.css:
.box {
width: 100px;
height: 100px;
background: #007bff;
position: absolute;
top: 50px;
left: 50px;
cursor: move;
}
Update script.js:
const box = document.getElementById('draggable');
let isDragging = false;
let startX, startY;
box.addEventListener('mousedown', e => {
isDragging = true;
startX = e.clientX - startX;
startY = e.clientY - startY;
});
document.addEventListener('mousemove', e => {
if (!isDragging) return;
const x = e.clientX - startX;
const y = e.clientY - startY;
box.animate(
[
{ transform: `translate(${x}px, ${y}px)` }
],
{ duration: 0, fill: 'forwards' }
);
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
box.animate(
[
{ transform: 'scale(1)', backgroundColor: '#007bff' },
{ transform: 'scale(1.2)', backgroundColor: '#ff5733' }
],
{
duration: 1000,
iterations: Infinity,
direction: 'alternate'
}
);
Dragging updates the box’s position in real-time, and releasing the mouse resumes the scale and color animation. fill: 'forwards' persists the dragged position.
Real-World Scenario: E-commerce Product Card
Create a product card with hover animations.
Update index.html:
<div class="product-card">
<img src="https://via.placeholder.com/150" alt="Product" />
<h2>Product Name</h2>
<p>$99.99</p>
</div>
Update style.css:
.product-card {
width: 200px;
padding: 20px;
border: 1px solid #ccc;
border-radius: 8px;
text-align: center;
}
img {
width: 100%;
}
Update script.js:
const card = document.querySelector('.product-card');
const img = card.querySelector('img');
card.addEventListener('mouseenter', () => {
img.animate(
[
{ transform: 'scale(1)', opacity: 1 },
{ transform: 'scale(1.1)', opacity: 0.8 }
],
{
duration: 300,
easing: 'ease-out',
fill: 'forwards'
}
);
});
card.addEventListener('mouseleave', () => {
img.animate(
[
{ transform: 'scale(1.1)', opacity: 0.8 },
{ transform: 'scale(1)', opacity: 1 }
],
{
duration: 300,
easing: 'ease-out',
fill: 'forwards'
}
);
});
Hovering scales and fades the image; moving away reverses it. The short animation enhances interactivity.
Conclusion (Technical Details)
The Web Animations API enables flexible, high-performance browser animations. The examples demonstrated:
- Basic movement, scaling, and color animations.
- Dynamic keyframes and controls (pause, play, reverse).
- Sequential and parallel animations.
- Integration with React and Vue.
- Interactive drag and e-commerce card animations.
Run these examples, inspect frame rates and performance in DevTools, and experience the smoothness of the Web Animations API!
Top comments (0)