CSS — Animations
Transitions react; animations perform
Transitions need a state change (hover). @keyframes plays on its own:
@keyframes slide-in {
from { transform: translateX(-100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.toast {
animation: slide-in 0.4s ease-out;
}
Anatomy
animation: slide-in 0.4s ease-out 0.2s 1 normal both;
───┬─── ──┬─ └───┬─── ─┬─ ┬──── ─┬─
name duration timing delay count direction fill
| Property | Job |
|---|---|
| name | which @keyframes |
| duration | total time |
| timing-function | easing per cycle (ease-out for entrances) |
| delay | wait before starting |
| iteration-count | number or infinite |
| direction | normal · reverse · alternate |
| fill-mode | what styles apply before/after (both keeps the end state!) |
Multi-step keyframes
Percentages mark stops between 0% and 100%:
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.15); opacity: 0.7; }
}
.notification-dot {
animation: pulse 1.5s ease-in-out infinite;
}
(A pulsing notification badge.)
The essential recipes
Spinner
@keyframes spin { to { transform: rotate(360deg); } }
.spinner {
width: 32px; height: 32px;
border: 3px solid #ddd;
border-top-color: teal;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
Bounce
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-12px); }
}
.scroll-hint { animation: bounce 1s infinite; }
Fade-up entrance
@keyframes fade-up {
from { opacity: 0; transform: translateY(16px); }
}
.card { animation: fade-up 0.5s ease-out both; }
both = element starts hidden even before the animation begins.
Staggering lists
Delay per child via nth-child or CSS variable:
.list-item { animation: fade-up .4s ease-out both; }
.list-item:nth-child(2) { animation-delay: .1s; }
.list-item:nth-child(3) { animation-delay: .2s; }
/* scalable: */
.list-item { animation-delay: calc(var(--i) * 80ms); }
(Items cascade in one after another.)
Pausing & responding to state
.paused { animation-play-state: paused; }
card.style.animationPlayState = "paused";
Respect reduced motion — always
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
}
}
Motion-sensitive users get instant states instead of loops.
Performance: animate only
transformandopacity. Animatingtop/width/marginrecalculates layout every frame — the difference between 60fps and stutter.
Transition vs animation? State reaction → transition. Autonomous performance → keyframes.
Mini Practice
- Spinner + "Loading…" text; remove after fetch resolves.
- Pulsing notification dot.
- Staggered three-card fade-up with delays.
- Alternating-direction slide (direction: alternate).
- Paused-on-hover marquee via play-state.
- Install the reduced-motion guard; verify with OS setting.
Next: tooltips →
Related Topics
Frequently Asked Questions about Animations
What is Animations in CSS?
Animations is a fundamental concept in CSS. This lesson explains it step by step with clear examples, making it easy for beginners to understand.
How do I learn Animations?
Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Animations.
Why is Animations important in CSS?
Animations is essential for CSS development. Understanding this concept will help you write better code and solve real-world problems more effectively.