CSS Keyframe Animation Delay and Iterations: A Complete Guide

Learn how to control animation timing, create pauses between cycles, and build performant, accessible animations with CSS.

CSS animations have evolved into a powerful tool for creating engaging user experiences on the modern web. Two properties that developers frequently overlook are animation-delay and animation-iteration-count. When combined strategically, these properties give you precise control over timing, allowing you to create animations that pause between iterations, stagger multi-element effects, and deliver polished interactions without relying on JavaScript.

This guide explores how to leverage these properties effectively in your Next.js projects and beyond.

Understanding the animation-delay Property

The animation-delay property specifies the amount of time to wait from applying the animation to an element before beginning to perform the animation. This property is fundamental for creating staggered animations, sequencing multiple effects, and improving perceived performance by delaying non-critical animations.

When building modern web interfaces, understanding how to control animation timing is essential for creating polished user experiences. Combined with other CSS techniques like CSS custom properties and CSS Grid layouts, these properties give you precise control over the timing and rhythm of your animations.

Key use cases:

  • Delaying animation start for sequencing effects
  • Creating staggered animations across multiple elements
  • Improving page load perception by deferring non-critical animations
  • Synchronizing multiple animations to start at different offsets
animation-delay Syntax
1/* Positive delay - wait before starting */2animation-delay: 2s;3animation-delay: 500ms;4 5/* Negative delay - start mid-animation */6animation-delay: -1s;7animation-delay: -500ms;8 9/* Multiple animations */10animation-delay: 0.5s, 1s, 1.5s;

Negative Delay Values: Starting Mid-Animation

One of the most powerful features of animation-delay is support for negative values. When you specify a negative delay, the animation begins immediately but starts partway through its cycle. For example, animation-delay: -1s means the animation starts as if it has already been running for 1 second.

Practical applications:

  • Synchronizing animations to a specific point in their cycle
  • Creating "resume" effects where animations pick up where they left off
  • Preloading animation states for JavaScript control
  • Coordinating multiple elements to appear at the same animation state

Controlling Repetition with animation-iteration-count

The animation-iteration-count CSS property sets the number of times an animation sequence should be played before stopping. Combined with delay, this gives you complete control over animation cycles.

Core concepts:

  • Default behavior: Animation plays once (count: 1)
  • Finite repetition: Specify exact number of iterations
  • Infinite looping: Use 'infinite' for continuous animations
  • Partial iterations: Non-integer values play partial cycles
animation-iteration-count Syntax
1/* Play once (default) */2animation-iteration-count: 1;3 4/* Play multiple times */5animation-iteration-count: 3;6animation-iteration-count: 10;7 8/* Play forever */9animation-iteration-count: infinite;10 11/* Partial iteration - plays half the cycle */12animation-iteration-count: 0.5;13 14/* Multiple animations */15animation-iteration-count: 2, infinite, 3;

Creating Pauses Between Iterations

One of the most common requirements in animation design is creating a pause between iterations. CSS animations don't have a built-in "pause between iterations" property, but there are several effective techniques to achieve this effect.

Technique 1: Multiple Keyframes with Pause States

The cleanest approach is to incorporate pause states directly into your keyframe definition by holding a position for the desired duration:

@keyframes pulse-with-pause {
 0%, 100% {
 transform: scale(1);
 opacity: 1;
 }
 25% {
 transform: scale(1.1);
 opacity: 0.8;
 }
 50% {
 /* Pause state - hold the scaled position */
 transform: scale(1.1);
 opacity: 0.8;
 }
 75% {
 transform: scale(1);
 opacity: 1;
 }
}

.element {
 animation: pulse-with-pause 4s ease-in-out infinite;
}

In this example, the 25-50% range creates a visible pause between the scale up and scale down phases.

Technique 2: Sequential Animation Properties

For cleaner separation of animation and pause, use the animation's natural timing with adjusted keyframe percentages:

@keyframes breathe {
 0%, 70%, 100% {
 transform: scale(1);
 }
 35% {
 transform: scale(1.1);
 }
}

@keyframes idle {
 0%, 35%, 70%, 100% {
 opacity: 1;
 }
 50%, 60% {
 opacity: 0.7;
 }
}

.element {
 animation: breathe 4s ease-in-out infinite;
}

This technique works well for "breathing" effects where the element expands, holds, contracts, and holds again.

Performance Considerations

CSS animations are generally GPU-accelerated and performant, but there are important considerations for optimal results. When building high-performance web applications, animation performance plays a crucial role in user experience and Core Web Vitals metrics.

Key Performance Guidelines

  1. Property selection: Animate only transform and opacity for best performance
  2. will-change hint: Use sparingly to inform the browser about upcoming animations
  3. Animation duration impact: Longer animations use fewer resources per iteration
  4. Repetition overhead: Infinite animations have ongoing computational cost

Common Use Cases and Code Examples

Loading Indicators

@keyframes loading-dots {
 0%, 20% { opacity: 0; transform: translateY(0); }
 30%, 100% { opacity: 1; transform: translateY(-5px); }
}

.dot {
 animation: loading-dots 1.5s ease-in-out infinite;
}

.dot:nth-child(1) { animation-delay: 0s; }
.dot:nth-child(2) { animation-delay: 0.2s; }
.dot:nth-child(3) { animation-delay: 0.4s; }

Card Hover with Repeated Pulse

@keyframes pulse {
 0%, 100% {
 box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4);
 }
 50% {
 box-shadow: 0 0 0 15px rgba(59, 130, 246, 0);
 }
}

.card:hover {
 animation: pulse 2s ease-out 3; /* Pulse 3 times on hover */
}

Staggered List Animation

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

.list-item {
 animation: slide-up 0.5s ease-out forwards;
 opacity: 0;
}

.list-item:nth-child(1) { animation-delay: 0.1s; }
.list-item:nth-child(2) { animation-delay: 0.2s; }
.list-item:nth-child(3) { animation-delay: 0.3s; }
.list-item:nth-child(4) { animation-delay: 0.4s; }
.list-item:nth-child(5) { animation-delay: 0.5s; }

Accessibility Considerations

Not all users appreciate or can tolerate motion on web pages. Motion can cause discomfort or even seizures in some individuals with vestibular disorders. Following accessibility best practices ensures your animations enhance rather than hinder the user experience for all visitors.

Respecting User Preferences

/* Disable or reduce motion for users who prefer it */
@media (prefers-reduced-motion: reduce) {
 .animated {
 animation: none !important;
 transition: none !important;
 }

 /* Or provide a subtle alternative */
 .animated-fallback {
 animation: subtle-pulse 2s ease-in-out infinite;
 }
}

Guidelines for Animation Use

  • Avoid auto-playing infinite animations near interactive elements
  • Provide controls to pause or stop animations when possible
  • Keep animations under 5 seconds unless they're subtle background effects
  • Avoid large-scale transforms that can trigger motion sickness

Integration with Next.js

CSS animations integrate seamlessly with Next.js development. Here are some practical patterns:

Client-Side Animation Component

'use client';

export default function AnimatedList({ items }) {
 return (
 <div className="space-y-2">
 {items.map((item, index) => (
 <div
 key={item.id}
 className="animated-item"
 style={{ animationDelay: `${index * 0.1}s` }}
 >
 {item.content}
 </div>
 ))}
 </div>
 );
}

CSS Modules Pattern

import styles from './PulsingButton.module.css';

export default function PulsingButton({ children, onClick }) {
 return (
 <button className={styles.pulse} onClick={onClick}>
 {children}
 </button>
 );
}
/* PulsingButton.module.css */
.pulse {
 animation: pulse 2s ease-in-out infinite;
}

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

Advanced Techniques

Synchronizing Multiple Animations

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes scale-up { from { transform: scale(0.9); } to { transform: scale(1); } }
@keyframes slide-up { from { transform: translateY(10px); } to { transform: translateY(0); } }

.coordinated .element-1 { animation: fade-in 0.5s ease-out both; }
.coordinated .element-2 { animation: scale-up 0.5s ease-out 0.1s both; }
.coordinated .element-3 { animation: slide-up 0.5s ease-out 0.2s both; }

Dynamic Iteration Control with CSS Variables

:root {
 --animation-iterations: 3;
 --animation-delay: 0.5s;
}

.dynamic-animation {
 animation: fade-in 1s ease-in-out var(--animation-iterations);
 animation-delay: var(--animation-delay);
}
CSS vs JavaScript Animations Comparison
AspectCSS AnimationsJavaScript Animations
PerformanceGPU-acceleratedMain thread
ControlLimited to CSS propertiesFull programmatic control
ComplexitySimple for basic casesMore code but more flexibility
DebuggingHarder to inspectEasier with dev tools
Best forLooping, repeating effectsComplex sequencing, physics

Summary and Best Practices

CSS keyframe animations with delay and iteration control offer powerful capabilities for creating polished user experiences:

  • Start with clear timing goals: Define whether you need delays, pauses, or both
  • Use negative delays for synchronization: They're more efficient than positive delays for staggered effects
  • Incorporate pauses in keyframes: The cleanest approach for predictable timing
  • Prioritize performance: Animate transform and opacity, respect prefers-reduced-motion
  • Test across browsers: Both properties are well-supported but verify your target platforms

By mastering these properties, you can create sophisticated animations that enhance user engagement without sacrificing performance or accessibility.

Frequently Asked Questions

Ready to Build Better Web Experiences?

Our team specializes in creating performant, accessible web interfaces with modern CSS techniques.