Codectionary / Developer documentation / CSS

Animations & @keyframes

@keyframes defines a named sequence of styles at different points (0% to 100%) of an animation, which is then applied to an element via the animation property. Unlike transitions, which only animate between two states, keyframe animations can define arbitrarily complex multi-step sequences and loop indefinitely.

Syntax

@keyframes name { 0% { } 100% { } }
animation: name duration timing-function iteration-count;

Examples

A Basic Keyframe Animation

Defining and applying a fade-in-and-rise animation.

/* Demo setup: sizing, structure or neutral surfaces. */
.preview-animation{padding:1.5rem;background:#dcfce7;color:#14532d;border:1px solid #16a34a}.loading-dot{display:inline-block;width:2rem;height:2rem;background:#c2410c;border-radius:50%;margin:2rem}

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

.card {
  animation: fadeInUp 0.5s ease-out;
}
  1. The target element matches the animation selector, so keyframes are applied to something visible.
  2. Run the example again to replay the entrance animation from its start.
  3. For production motion, respect reduced-motion preferences and avoid using motion as the only status information.
HTML used by this example
<div class="card preview-animation">A newly revealed lesson</div>

Multi-Step and Looping Animation

A pulsing loading indicator using percentage-based keyframes.

/* Demo setup: sizing, structure or neutral surfaces. */
.preview-animation{padding:1.5rem;background:#dcfce7;color:#14532d;border:1px solid #16a34a}.loading-dot{display:inline-block;width:2rem;height:2rem;background:#c2410c;border-radius:50%;margin:2rem}

@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.5; transform: scale(1.1); }
}

.loading-dot {
  animation: pulse 1.5s ease-in-out infinite;
}
  1. The target element matches the animation selector, so keyframes are applied to something visible.
  2. The dot repeats its opacity and scale changes through the defined keyframe stops.
  3. For production motion, respect reduced-motion preferences and avoid using motion as the only status information.
HTML used by this example
<span class="loading-dot" role="img" aria-label="Decorative pulsing status dot"></span><p>This is a visual animation demo, not a real loading request.</p>

Parameters and values

  • animation-name (identifier): References a @keyframes rule by name
  • animation-duration (time): Length of one animation cycle
  • animation-iteration-count (number | infinite): How many times the animation repeats
  • animation-fill-mode (none | forwards | backwards | both): What styles apply before/after the animation runs

Best practices

  • Use @keyframes for multi-step or looping animations, and simple transitions for animating between exactly two states
  • Set animation-fill-mode: forwards when the animation's end state should persist after it finishes, rather than snapping back to the original style
  • Use infinite only for genuinely continuous effects like loading spinners - most UI animations should run once
  • Wrap non-essential animations in an @media (prefers-reduced-motion: no-preference) query so users with motion sensitivity are not affected

Browser compatibility

chrome
Yes
firefox
Yes
safari
Yes
edge
Yes

These are the existing reference’s support labels, not tested minimum versions. Individual values and APIs can have different support. Check the linked specification before choosing a browser target.

CSS specifications (modules)

Specifications & further reading