Three tools: CSS, the Web Animations API, GSAP

There are three main ways to animate in the browser.

  • CSS (transition, @keyframes) - hover, appearance and simple effects. Little code, and the browser optimizes it.
  • Web Animations API (element.animate()) - the power of CSS, but controlled from JS: pause(), reverse(), finished.
  • GSAP - complex sequences, timeline, ScrollTrigger, precise control, the same behavior across browsers.

Most of the time you do not need GSAP. CSS is enough for a button hover; add the library when you need sequences and scroll scenes.

ToolStrengthLimit
CSSSimple, no code, browser-optimizedHard to sequence and control
animate()JS control, finished, reverseNo timeline or scroll scenes
GSAPtimeline, ScrollTrigger, stagger, precisionAn extra dependency, bundle size

CSS animations

transition moves between two states (for example on hover). @keyframes describes a multi-step animation and is attached with animation. The code below ends with a prefers-reduced-motion block: it is worth writing once for the whole project.

css
.card {
  transition: transform 0.3s ease, opacity 0.3s ease;
}
.card:hover {
  transform: translateY(-4px);
}

@keyframes fade-up {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}
.hero {
  animation: fade-up 0.6s ease-out both;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

💡 The both value of animation keeps the first frame before the start and the last frame after the end.


The Web Animations API

element.animate(keyframes, options) works like a CSS animation but returns an Animation object. With it you can pause the animation, change its speed, play it backwards and wait for the end through the finished promise.

javascript
const box = document.querySelector('.box');