CSS Effects April 2026 · 10 min read

CSS Animations & Keyframes: The Complete Guide

CSS animations bring interfaces to life — but done wrong, they slow pages down and frustrate users. This guide covers the full picture: from basic keyframe syntax to performance-safe techniques and accessibility requirements.

The Two CSS Animation Systems

CSS has two ways to animate: transitions (for state changes triggered externally) and animations (for self-playing sequences). Both have their place:

/* Transition: responds to class/state change */
.btn {
  background: #7c5cfc;
  transition: background 0.2s ease, transform 0.2s ease;
}
.btn:hover {
  background: #9333ea;
  transform: translateY(-2px);
}

/* Animation: runs automatically */
.spinner {
  animation: spin 1s linear infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

@keyframes Syntax

The @keyframes rule defines the sequence of styles at specific points in time. You can use percentages or the keywords from / to:

@keyframes fadeSlideIn {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Multi-step keyframes */
@keyframes pulse {
  0%   { transform: scale(1); opacity: 1; }
  50%  { transform: scale(1.05); opacity: 0.8; }
  100% { transform: scale(1); opacity: 1; }
}

The animation Shorthand

The animation property is shorthand for 8 individual properties:

.element {
  animation: name duration timing-function delay
             iteration-count direction fill-mode play-state;

  /* Example */
  animation: fadeSlideIn 0.4s ease-out 0.1s 1 normal forwards running;

  /* Most common — name, duration, easing */
  animation: fadeSlideIn 0.4s ease-out;

  /* Multiple animations */
  animation: fadeSlideIn 0.4s ease-out, pulse 2s ease-in-out 1s infinite;
}

Timing Functions Explained

The timing function controls the rate of change throughout the animation. Understanding the options is key to animations that feel natural:

.element {
  /* Built-in keywords */
  animation-timing-function: ease;        /* slow start, fast middle, slow end */
  animation-timing-function: ease-in;     /* slow start, accelerates */
  animation-timing-function: ease-out;    /* fast start, decelerates */
  animation-timing-function: ease-in-out; /* slow start and end */
  animation-timing-function: linear;      /* constant speed (good for rotations) */

  /* Custom cubic-bezier */
  animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1); /* spring bounce */

  /* Steps (for sprite animations or typewriter effects) */
  animation-timing-function: steps(8, end);
}

For most UI animations, ease-out feels the most natural — objects that enter the screen decelerate as they arrive, like real physical objects. Reserve ease-in for elements leaving the screen.

fill-mode: What Happens Before and After

animation-fill-mode controls the element's style outside the animation's active duration:

.element {
  /* none (default): returns to original state after animation */
  animation-fill-mode: none;

  /* forwards: keeps final keyframe values after animation ends */
  animation-fill-mode: forwards;

  /* backwards: applies first keyframe values during delay period */
  animation-fill-mode: backwards;

  /* both: applies backwards + forwards */
  animation-fill-mode: both;
}

/* Most fade-in animations need "both" to avoid flash before start */
.fade-in {
  opacity: 0;
  animation: fadeIn 0.5s ease-out 0.2s both;
}
@keyframes fadeIn { to { opacity: 1; } }

Performance: Only Animate These Properties

CSS animations can trigger three different browser pipeline stages: layout, paint, and composite. Only composited properties are GPU-accelerated and smooth at 60fps:

/* ✅ GPU-composited: always smooth */
transform: translate(), scale(), rotate(), skew()
opacity

/* ⚠️ Triggers paint: avoid animating on many elements */
color, background-color, border-color, box-shadow

/* ❌ Triggers layout: never animate these */
width, height, padding, margin, top, left, font-size

/* Promote to GPU layer if needed */
.animated-element {
  will-change: transform; /* Use sparingly — right before animation */
}

Accessibility: Respecting Motion Preferences

Users with vestibular disorders or motion sensitivity can set their OS to "reduce motion". Always respect this preference:

/* Define animation normally */
.card {
  animation: slideIn 0.5s ease-out both;
}

/* Disable or reduce for users who prefer less motion */
@media (prefers-reduced-motion: reduce) {
  .card {
    animation: none; /* or a gentler alternative */
  }

  /* For transitions */
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

The nuclear option (setting all durations to 0.01ms) works but may cause jarring instant state changes. A better approach is to define a simplified, opacity-only version of each animation for reduced-motion users rather than removing all animation entirely.

Common Animation Patterns

These are the animations that appear most frequently in production UI:

/* Fade in */
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Slide up (enter from below) */
@keyframes slideUp {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Scale pop (for modals, tooltips) */
@keyframes scalePop {
  from { opacity: 0; transform: scale(0.92); }
  to   { opacity: 1; transform: scale(1); }
}

/* Shimmer (loading skeleton) */
@keyframes shimmer {
  from { background-position: -200% center; }
  to   { background-position: 200% center; }
}
.skeleton {
  background: linear-gradient(90deg, #1a1a2e 25%, #2a2a4e 50%, #1a1a2e 75%);
  background-size: 200% auto;
  animation: shimmer 1.5s linear infinite;
}

Common Mistakes

Related guides

palette

Gradient Generator

Animated gradient backgrounds

layers

Glassmorphism Generator

Animated glass UI

Free reference

The 47 Tools Cheat Sheet

One printable page with every tool on this site, what it does, and when to reach for it. Free. It asks for an email so Gumroad can send you the file, unlike the tools themselves.