CSS Animation Not Playing — How to Fix (2026) | Tutorials Logic
Why is CSS Animation Not Playing?
CSS animations require several properties to work together correctly. When an animation doesn't play, it's usually due to a missing animation-duration, a typo in the animation-name that doesn't match the @keyframes name, or the animation being paused.
Common Symptoms:
Animation not starting • Animation plays once then stops • Animation jumps instead of transitioning smoothly
Animation not starting • Animation plays once then stops • Animation jumps instead of transitioning smoothly
Common Causes
Quick Fix (TL;DR)
/* ❌ Problem — missing duration */
.element { animation: fadeIn; } /* Duration defaults to 0s! */
/* ✅ Solution — always include duration */
.element {
animation: fadeIn 1s ease-in-out;
/* name | duration | timing | (optional: delay, iteration, direction) */
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
Common Scenarios & Solutions
Scenario 1: @keyframes Name Mismatch
/* ❌ Name mismatch */
.element { animation: fade-in 1s; } /* "fade-in" */
@keyframes fadeIn { /* "fadeIn" — different! */
from { opacity: 0; }
to { opacity: 1; }
}
/* ✅ Names must match exactly (case-sensitive) */
.element { animation: fadeIn 1s ease; }
@keyframes fadeIn { /* Exact match */
from { opacity: 0; }
to { opacity: 1; }
}
Scenario 2: Animation Plays Once and Stops
/* ✅ Loop animation infinitely */
.spinner {
animation: spin 1s linear infinite; /* infinite = loop forever */
}
/* ✅ Keep final state after animation */
.element {
animation: slideIn 0.5s ease forwards; /* forwards = keep end state */
}
/* ✅ Alternate direction */
.pulse {
animation: pulse 1s ease-in-out infinite alternate;
/* alternate = plays forward then backward */
}
Scenario 3: Respecting prefers-reduced-motion
/* ✅ Respect user's motion preference */
.animated {
animation: bounce 0.5s infinite;
}
@media (prefers-reduced-motion: reduce) {
.animated {
animation: none; /* Disable for users who prefer less motion */
}
}
/* ✅ Or use a subtle alternative */
@media (prefers-reduced-motion: reduce) {
.animated {
animation-duration: 0.01ms; /* Effectively instant */
}
}
Scenario 4: Complete Animation Example
/* ✅ Complete animation with all properties */
.notification {
animation-name: slideDown;
animation-duration: 0.4s;
animation-timing-function: ease-out;
animation-delay: 0.1s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-play-state: running;
/* Shorthand: name duration timing delay count direction fill-mode */
animation: slideDown 0.4s ease-out 0.1s 1 normal forwards;
}
@keyframes slideDown {
from { transform: translateY(-100%); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
Best Practices to Avoid This Error
Related Issues
Key Takeaways
- animation-duration defaults to 0s — always specify a duration or the animation is invisible
- @keyframes name must exactly match the animation-name value (case-sensitive)
- Use animation-fill-mode: forwards to keep the final state after the animation ends
- Use animation-iteration-count: infinite for looping animations
- Always add a prefers-reduced-motion media query for accessibility
- Animate transform and opacity for best performance — they use GPU acceleration
Frequently Asked Questions
Level Up Your Css Skills
Master Css with these hand-picked resources
10,000+ learners
Free forever
Updated 2026
Related CSS Topics