Web Animations Guide

CSS Animations

/* Define keyframes */ @keyframes slideIn { from { transform: translateY(-20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } } /* Apply animation */ .modal { animation: slideIn 300ms ease-out both; } .badge { animation: pulse 2s ease-in-out infinite; } /* animation shorthand: name duration timing-function delay iteration direction fill-mode */ .card:hover { animation: pulse 400ms ease-in-out 0s 1 normal forwards; } /* Multiple animations */ .element { animation: slideIn 0.3s ease, pulse 2s 0.3s infinite; }

Web Animations API (WAAPI)

// Basic animation const el = document.querySelector('.box'); const animation = el.animate([ { transform: 'translateX(0)', opacity: 1 }, { transform: 'translateX(200px)', opacity: 0.5 }, { transform: 'translateX(400px)', opacity: 0 } ], { duration: 1000, // ms easing: 'ease-in-out', delay: 0, fill: 'forwards', // persist end state iterations: 1, // Infinity for looping direction: 'alternate' }); // Control playback animation.pause(); animation.play(); animation.reverse(); animation.cancel(); animation.finish(); // Events animation.finished.then(() => console.log('Done!')); animation.onfinish = () => el.remove();

Animation Timing Functions

FunctionDescriptionFeel
linearConstant speedMechanical
easeSlow start, fast middle, slow endNatural (default)
ease-inStarts slowObjects leaving
ease-outEnds slowObjects entering
ease-in-outBoth slowObjects passing through
cubic-bezier()Custom curveAny feel
spring()Physics-based springBouncy, natural

Performance Best Practices

/* Only animate GPU-composited properties */ /* GOOD — no layout/paint triggered */ .anim { transform: translateX(100px) scale(1.1) rotate(45deg); opacity: 0.5; filter: blur(4px); } /* BAD — triggers layout */ .bad-anim { top: 100px; /* layout */ left: 100px; /* layout */ width: 200px; /* layout */ margin: 10px; /* layout */ } /* Hint browser to prepare compositing layer */ .will-animate { will-change: transform, opacity; } /* Remove after animation to free memory */ element.addEventListener('animationend', () => { element.style.willChange = 'auto'; });