</>
Skip to content
CSS lessons (53/66)

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
PropertyJob
namewhich @keyframes
durationtotal time
timing-functioneasing per cycle (ease-out for entrances)
delaywait before starting
iteration-countnumber or infinite
directionnormal · reverse · alternate
fill-modewhat 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 transform and opacity. Animating top/width/margin recalculates layout every frame — the difference between 60fps and stutter.

Transition vs animation? State reaction → transition. Autonomous performance → keyframes.

Mini Practice

  1. Spinner + "Loading…" text; remove after fetch resolves.
  2. Pulsing notification dot.
  3. Staggered three-card fade-up with delays.
  4. Alternating-direction slide (direction: alternate).
  5. Paused-on-hover marquee via play-state.
  6. 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.