LearnContact
Lesson 2225 min read

CSS Animation

Learn how CSS animations create multi-step, repeating, automatic, and controlled motion using @keyframes and animation properties.

Introduction

In the previous lesson, you learned CSS Transition and how property values can change smoothly from one state to another.

Transitions are excellent for simple state changes such as hover effects, focus states, and class changes.

However, some visual effects require multiple steps, automatic playback, repetition, direction control, pausing, and more complex motion sequences.

CSS Animation provides these capabilities using the @keyframes rule and animation properties.

Define Keyframes
Give Animation a Name
Apply Animation to Element
Browser Calculates Frames
Animation Runs
Animation Repeats or Ends
Animations Can Run Automatically

Unlike transitions, CSS animations do not always require a state change such as :hover. They can begin automatically when an element appears.

What is CSS Animation?

CSS Animation is a feature that allows an element to change through one or more visual states over time.

The animation sequence is defined using @keyframes, while animation properties control how the sequence runs.

Simple Animation
@keyframes move {
    from {
        transform: translateX(0);
    }

    to {
        transform: translateX(200px);
    }
}

.box {
    animation:
        move 2s ease;
}
Animation Concept
Start State
    │
    ▼
Intermediate Frames
    │
    ▼
Final State


0% ───────── 25% ───────── 50% ───────── 75% ───────── 100%

Why Do We Need Animations?

Animations are useful when an interface needs motion that is more complex than a simple change between two states.

Multi-Step Motion

Create sequences with several intermediate states.

Repetition

Repeat animations a specific number of times or forever.

Automatic Playback

Start animations without requiring hover or another state change.

Direction Control

Play animations forward, backward, or alternate directions.

Play and Pause

Pause and resume animations when required.

Visual Feedback

Draw attention to loading, notifications, success states, and updates.

Real-World Analogy

Imagine creating a flipbook animation.

Each important drawing represents a key moment. When the pages are shown quickly, the drawings appear to move.

Flipbook ConceptCSS Animation
Animation sequence@keyframes
Important drawingsKeyframes
First drawing0% or from
Last drawing100% or to
Playback speedanimation-duration
Number of repeatsanimation-iteration-count
Playback directionanimation-direction
Flipbook Analogy
Frame 1     Frame 2     Frame 3     Frame 4

   ●            ●            ●            ●
   │           ╱             ─             ╲
  ╱ ╲         ╱ ╲           ╱ ╲           ╱ ╲

     Rapid Playback Creates Motion


CSS

0% ───────► 33% ───────► 66% ───────► 100%

Transition vs Animation

CSS Transition

  • Usually needs a property state change.
  • Commonly moves between two states.
  • Ideal for hover and focus effects.
  • Simple to configure.
  • Automatically reverses when state changes back.

CSS Animation

  • Can start automatically.
  • Can contain many keyframes.
  • Can repeat automatically.
  • Can control direction and fill mode.
  • Ideal for complex motion sequences.
FeatureTransitionAnimation
Needs state changeUsuallyNo
Multiple stepsLimitedYes
Automatic startNot normallyYes
RepeatNo built-in repetitionYes
Direction controlLimitedYes
Pause and resumeLimitedYes
Uses @keyframesNoYes

How CSS Animation Works

A CSS animation requires keyframes and an element that references those keyframes using animation-name or the animation shorthand.

Create @keyframes
Name the Animation
Define Animation States
Apply Name to Element
Set Duration
Browser Generates Intermediate Frames
Animation Plays
Animation Process
@keyframes grow {
    from {
        transform: scale(1);
    }

    to {
        transform: scale(1.3);
    }
}

.box {
    animation-name: grow;

    animation-duration: 1s;
}
Keyframes Define the Sequence

The @keyframes rule describes what changes. Animation properties describe how the sequence should run.

The @keyframes Rule

The @keyframes rule defines the visual states of an animation.

Keyframes Syntax
@keyframes animationName {
    from {
        /* Starting styles */
    }

    to {
        /* Ending styles */
    }
}
Percentage Syntax
@keyframes animationName {
    0% {
        /* Starting styles */
    }

    50% {
        /* Middle styles */
    }

    100% {
        /* Ending styles */
    }
}

Basic Animation Syntax

Longhand Syntax
.element {
    animation-name: move;

    animation-duration: 2s;

    animation-timing-function: ease;

    animation-delay: 0s;

    animation-iteration-count: 1;

    animation-direction: normal;

    animation-fill-mode: none;

    animation-play-state: running;
}
Shorthand Syntax
.element {
    animation:
        move
        2s
        ease
        0s
        1
        normal
        none
        running;
}

Example 1: Moving Box

HTML
<div class="moving-box">
    Move
</div>
CSS
@keyframes moveBox {
    from {
        transform:
            translateX(0);
    }

    to {
        transform:
            translateX(250px);
    }
}

.moving-box {
    width: 80px;
    height: 80px;

    display: grid;

    place-items: center;

    background: #6c5ce7;
    color: white;

    border-radius: 12px;

    animation-name:
        moveBox;

    animation-duration:
        2s;
}

from and to Keywords

The from keyword represents the beginning of an animation, while to represents the end.

KeywordEquivalent Percentage
from0%
to100%
Equivalent Keyframes
@keyframes fadeOne {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes fadeTwo {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

Percentage Keyframes

Percentage keyframes allow an animation to contain many important states.

Multiple Keyframes
@keyframes change {
    0% {
        transform:
            translateX(0);

        background:
            #6c5ce7;
    }

    25% {
        transform:
            translateX(100px);

        background:
            #0984e3;
    }

    50% {
        transform:
            translateX(200px);

        background:
            #00b894;
    }

    75% {
        transform:
            translateX(100px);

        background:
            #fdcb6e;
    }

    100% {
        transform:
            translateX(0);

        background:
            #6c5ce7;
    }
}
Percentages Represent Animation Progress

The percentage does not represent seconds. It represents a position within the total animation duration.

Example 2: Multi-Step Animation

HTML
<div class="multi-box"></div>
CSS
@keyframes travel {
    0% {
        transform:
            translate(0, 0);
    }

    25% {
        transform:
            translate(220px, 0);
    }

    50% {
        transform:
            translate(220px, 100px);
    }

    75% {
        transform:
            translate(0, 100px);
    }

    100% {
        transform:
            translate(0, 0);
    }
}

.multi-box {
    width: 60px;
    height: 60px;

    background: #6c5ce7;

    border-radius: 12px;

    animation:
        travel 4s ease infinite;
}

Animation Properties

PropertyPurpose
animation-nameSelects the @keyframes animation
animation-durationDefines how long one cycle takes
animation-timing-functionControls the speed curve
animation-delayDefines waiting time before starting
animation-iteration-countDefines number of repetitions
animation-directionControls playback direction
animation-fill-modeControls styles before and after animation
animation-play-stateRuns or pauses the animation
animationShorthand for animation properties

animation-name

The animation-name property connects an element to a named @keyframes rule.

Animation Name
@keyframes rotateBox {
    to {
        transform:
            rotate(360deg);
    }
}

.box {
    animation-name:
        rotateBox;
}
Names Must Match

If animation-name does not match an existing @keyframes name, the animation will not run.

animation-duration

The animation-duration property defines how long one complete animation cycle takes.

Animation Duration
.fast {
    animation-duration: 0.5s;
}

.medium {
    animation-duration: 2s;
}

.slow {
    animation-duration: 5s;
}
Default Duration Is 0s

An animation will not visibly run unless a duration greater than zero is provided.

Time Units

UnitMeaningExample
sSeconds2s
msMilliseconds500ms
Equivalent Durations
.one {
    animation-duration: 1s;
}

.two {
    animation-duration: 1000ms;
}

Example 3: Different Durations

HTML
<div class="duration-box fast">
    Fast
</div>

<div class="duration-box medium">
    Medium
</div>

<div class="duration-box slow">
    Slow
</div>
CSS
@keyframes slide {
    from {
        transform:
            translateX(0);
    }

    to {
        transform:
            translateX(250px);
    }
}

.duration-box {
    width: 90px;

    padding: 14px;

    margin-bottom: 12px;

    background: #6c5ce7;
    color: white;

    text-align: center;

    border-radius: 8px;

    animation-name:
        slide;

    animation-iteration-count:
        infinite;

    animation-direction:
        alternate;
}

.fast {
    animation-duration: 0.8s;
}

.medium {
    animation-duration: 2s;
}

.slow {
    animation-duration: 4s;
}

animation-timing-function

The animation-timing-function property controls how animation speed changes between keyframes.

Timing Function
.box {
    animation-timing-function:
        ease-in-out;
}

Timing Function Values

ValueBehavior
easeSlow start, faster middle, slow end
linearConstant speed
ease-inSlow start
ease-outSlow end
ease-in-outSlow start and slow end
cubic-bezier()Custom speed curve
steps()Movement in fixed jumps
Timing Applies Between Keyframes

When an animation contains several keyframes, the timing function controls movement between the keyframe states.

Example 4: Timing Functions

CSS
@keyframes race {
    from {
        transform:
            translateX(0);
    }

    to {
        transform:
            translateX(280px);
    }
}

.ease {
    animation:
        race 3s ease infinite alternate;
}

.linear {
    animation:
        race 3s linear infinite alternate;
}

.ease-in {
    animation:
        race 3s ease-in infinite alternate;
}

.ease-out {
    animation:
        race 3s ease-out infinite alternate;
}

animation-delay

The animation-delay property defines how long the browser waits before an animation starts.

Animation Delay
.box {
    animation-name: move;

    animation-duration: 2s;

    animation-delay: 1s;
}
Element Appears
Delay Begins
Browser Waits
Animation Starts
Animation Runs

Positive Delay

A positive animation delay waits before the animation begins.

Positive Delay
.box {
    animation:
        move 2s ease 1s;
}

Negative Delay

A negative animation delay starts the animation immediately as if part of the animation had already completed.

Negative Delay
.box {
    animation:
        move 4s linear -2s;
}
Useful for Staggered Continuous Animations

Negative delays are useful when several repeating elements should appear at different positions in the same animation cycle.

Example 5: Delayed Animation

CSS
@keyframes appear {
    from {
        opacity: 0;

        transform:
            translateY(30px);
    }

    to {
        opacity: 1;

        transform:
            translateY(0);
    }
}

.delay-card {
    animation:
        appear
        0.8s
        ease
        1.5s
        forwards;
}

animation-iteration-count

The animation-iteration-count property defines how many times an animation should repeat.

Repeat Three Times
.box {
    animation-iteration-count: 3;
}
ValueMeaning
1Runs once
2Runs twice
3Runs three times
0.5Runs half of one cycle
infiniteRepeats forever

Infinite Animation

The infinite keyword makes an animation repeat continuously.

Infinite Animation
.spinner {
    animation:
        rotate 1s linear infinite;
}
Use Infinite Motion Carefully

Continuous animation can distract users and consume resources. Use it only when the repeated motion serves a clear purpose.

Example 6: Repeating Animation

CSS
@keyframes blink {
    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.2;
    }
}

.status-dot {
    width: 18px;
    height: 18px;

    background: #00b894;

    border-radius: 50%;

    animation:
        blink
        1.2s
        ease-in-out
        infinite;
}

animation-direction

The animation-direction property controls the direction in which animation cycles play.

ValueBehavior
normalEvery cycle plays from start to end
reverseEvery cycle plays from end to start
alternateOdd cycles forward, even cycles backward
alternate-reverseOdd cycles backward, even cycles forward

normal

Normal Direction
Cycle 1: 0% ─────────► 100%

Cycle 2: 0% ─────────► 100%

reverse

Reverse Direction
Cycle 1: 100% ─────────► 0%

Cycle 2: 100% ─────────► 0%

alternate

Alternate Direction
Cycle 1: 0% ─────────► 100%

Cycle 2: 100% ─────────► 0%

Cycle 3: 0% ─────────► 100%

alternate-reverse

Alternate Reverse Direction
Cycle 1: 100% ─────────► 0%

Cycle 2: 0% ─────────► 100%

Cycle 3: 100% ─────────► 0%

Example 7: Animation Directions

CSS
.normal {
    animation-direction: normal;
}

.reverse {
    animation-direction: reverse;
}

.alternate {
    animation-direction: alternate;
}

.alternate-reverse {
    animation-direction:
        alternate-reverse;
}

animation-fill-mode

The animation-fill-mode property controls which keyframe styles apply before an animation starts and after it finishes.

ValueBehavior
noneNo keyframe styles retained outside animation
forwardsKeeps final keyframe styles after animation
backwardsApplies starting keyframe styles during delay
bothCombines forwards and backwards behavior

none

The none value is the default. The element returns to its normal CSS styles after the animation ends.

forwards

The forwards value keeps the styles from the animation final keyframe after the animation finishes.

Keep Final State
.box {
    animation:
        move 2s ease forwards;
}

backwards

The backwards value applies the starting keyframe styles during the animation delay.

both

The both value applies the behavior of both forwards and backwards.

Example 8: Fill Modes

CSS
@keyframes reveal {
    from {
        opacity: 0;

        transform:
            translateY(30px);
    }

    to {
        opacity: 1;

        transform:
            translateY(0);
    }
}

.card {
    animation:
        reveal
        1s
        ease
        1s
        both;
}
both Is Common for Entrance Animations

The both value can apply the starting state during a delay and preserve the ending state after the animation completes.

animation-play-state

The animation-play-state property controls whether an animation is running or paused.

ValueMeaning
runningAnimation plays normally
pausedAnimation stops at its current position

Pause on Hover

Pause Animation on Hover
.box {
    animation:
        rotate 3s linear infinite;
}

.box:hover {
    animation-play-state:
        paused;
}

Example 9: Play and Pause

CSS
@keyframes orbit {
    to {
        transform:
            rotate(360deg);
    }
}

.orbit {
    animation:
        orbit 3s linear infinite;
}

.orbit:hover {
    animation-play-state:
        paused;
}

Animation Shorthand

The animation shorthand combines several animation properties into one declaration.

Shorthand Syntax
.element {
    animation:
        name
        duration
        timing-function
        delay
        iteration-count
        direction
        fill-mode
        play-state;
}

Shorthand Order

Complete Shorthand
.box {
    animation:
        move
        2s
        ease-in-out
        0.5s
        infinite
        alternate
        both
        running;
}
ValueMeaning
moveAnimation name
2sDuration
ease-in-outTiming function
0.5sDelay
infiniteIteration count
alternateDirection
bothFill mode
runningPlay state
First Time Is Duration, Second Time Is Delay

When two time values appear in animation shorthand, the first is duration and the second is delay.

Example 10: Shorthand Animation

CSS
@keyframes float {
    from {
        transform:
            translateY(0);
    }

    to {
        transform:
            translateY(-25px);
    }
}

.float-card {
    animation:
        float
        1.5s
        ease-in-out
        0s
        infinite
        alternate;
}

Multiple Animations

An element can run several animations at the same time by separating animation definitions with commas.

Multiple Animations
.box {
    animation:
        move 3s ease infinite alternate,
        rotate 2s linear infinite,
        colorChange 4s ease infinite;
}

Example 11: Multiple Animations

CSS
@keyframes move {
    from {
        transform:
            translateX(0)
            rotate(0);
    }

    to {
        transform:
            translateX(220px)
            rotate(360deg);
    }
}

@keyframes changeColor {
    0% {
        background:
            #6c5ce7;
    }

    50% {
        background:
            #00b894;
    }

    100% {
        background:
            #e17055;
    }
}

.multi-animation {
    animation:
        move
        3s
        ease-in-out
        infinite
        alternate,

        changeColor
        4s
        linear
        infinite;
}

Transform Animations

The transform property is commonly animated for movement, rotation, scaling, and skewing.

Transform Animation
@keyframes transformExample {
    0% {
        transform:
            translateX(0)
            rotate(0)
            scale(1);
    }

    100% {
        transform:
            translateX(200px)
            rotate(360deg)
            scale(1.2);
    }
}
Transform Is Commonly Suitable for Motion

Animating transform often avoids repeated layout calculations and is widely used for smooth visual movement.

Example 12: Loading Spinner

HTML
<div class="spinner"></div>
CSS
@keyframes spin {
    to {
        transform:
            rotate(360deg);
    }
}

.spinner {
    width: 60px;
    height: 60px;

    border:
        7px solid #dfe6e9;

    border-top-color:
        #6c5ce7;

    border-radius: 50%;

    animation:
        spin
        0.8s
        linear
        infinite;
}

Opacity Animations

Animating opacity creates fade-in, fade-out, blinking, and reveal effects.

Opacity Animation
@keyframes fade {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

Example 13: Fade In

CSS
@keyframes fadeIn {
    from {
        opacity: 0;

        transform:
            translateY(20px);
    }

    to {
        opacity: 1;

        transform:
            translateY(0);
    }
}

.fade-card {
    animation:
        fadeIn
        0.8s
        ease
        both;
}

Bouncing Animation

A bouncing effect can be created by changing vertical translation at several keyframes.

Bounce Keyframes
@keyframes bounce {
    0%,
    100% {
        transform:
            translateY(0);
    }

    50% {
        transform:
            translateY(-80px);
    }
}

Example 14: Bouncing Ball

CSS
@keyframes bounceBall {
    0%,
    100% {
        transform:
            translateY(0)
            scaleX(1.1)
            scaleY(0.9);
    }

    50% {
        transform:
            translateY(-100px)
            scaleX(0.95)
            scaleY(1.05);
    }
}

.ball {
    width: 70px;
    height: 70px;

    background:
        #6c5ce7;

    border-radius: 50%;

    animation:
        bounceBall
        1s
        ease-in-out
        infinite;
}

Pulse Animation

A pulse animation repeatedly changes scale, opacity, or shadow to attract attention.

Example 15: Notification Pulse

CSS
@keyframes pulse {
    0% {
        transform:
            scale(1);

        box-shadow:
            0 0 0 0
            rgba(225, 112, 85, 0.5);
    }

    70% {
        transform:
            scale(1.08);

        box-shadow:
            0 0 0 18px
            rgba(225, 112, 85, 0);
    }

    100% {
        transform:
            scale(1);

        box-shadow:
            0 0 0 0
            rgba(225, 112, 85, 0);
    }
}

.notification {
    animation:
        pulse
        1.5s
        ease
        infinite;
}

Typing Animation

A typing effect can be created by animating width in discrete steps while hiding overflowing text.

Example 16: Typing Effect

HTML
<h2 class="typing">
    Learn CSS Animation
</h2>
CSS
@keyframes typing {
    from {
        width: 0;
    }

    to {
        width: 20ch;
    }
}

@keyframes cursor {
    50% {
        border-color:
            transparent;
    }
}

.typing {
    width: 20ch;

    overflow: hidden;

    white-space: nowrap;

    border-right:
        3px solid #6c5ce7;

    animation:
        typing
        3s
        steps(20)
        forwards,

        cursor
        0.7s
        step-end
        infinite;
}

Animation Events

JavaScript can listen for events generated by CSS animations.

EventWhen It Occurs
animationstartAnimation begins
animationiterationA new animation cycle begins
animationendAnimation finishes
animationcancelAnimation is cancelled
Animation Event
const box =
    document.querySelector('.box');

box.addEventListener(
    'animationend',
    () => {
        console.log(
            'Animation completed'
        );
    }
);

Controlling Animation with JavaScript

JavaScript can start, stop, pause, resume, or replace animations by changing classes and styles.

Toggle Animation Class
const box =
    document.querySelector('.box');

const button =
    document.querySelector('.button');

button.addEventListener(
    'click',
    () => {
        box.classList.toggle(
            'animate'
        );
    }
);
Animation Class
.box.animate {
    animation:
        bounce
        1s
        ease
        infinite;
}

Animation Performance

Animations can affect browser performance differently depending on which properties change and how many elements are animated.

Commonly Better for Motion

  • transform
  • opacity
  • Often avoids repeated layout calculations.
  • Suitable for frequent visual updates.

Can Require More Work

  • width
  • height
  • margin
  • top and left in complex layouts
Animate Purposefully

A smooth animation is not only about code. Avoid animating too many large elements at the same time.

prefers-reduced-motion

Some users prefer reduced motion. CSS can detect this preference and reduce or remove non-essential animations.

Reduce Animation
.card {
    animation:
        float 2s ease infinite alternate;
}

@media (
    prefers-reduced-motion:
    reduce
) {
    .card {
        animation: none;
    }
}
Keep Functionality Without Motion

Important information and controls should remain understandable and usable when animations are disabled.

Complete Animation Example

The following example combines entrance animations, floating motion, rotation, pulsing, staggered delays, multiple keyframes, and interactive animation states.

HTML
<section class="animation-showcase">
    <div class="showcase-content">
        <span class="showcase-badge">
            CSS Animation
        </span>

        <h2>
            Bring Interfaces to Life
        </h2>

        <p>
            Create smooth, meaningful,
            and engaging motion with CSS.
        </p>

        <button class="showcase-button">
            Start Learning

            <span>→</span>
        </button>
    </div>

    <div class="showcase-visual">
        <div class="orbit-ring ring-one">
            <span></span>
        </div>

        <div class="orbit-ring ring-two">
            <span></span>
        </div>

        <div class="center-icon">
            ✨
        </div>

        <div class="floating-card card-one">
            @keyframes
        </div>

        <div class="floating-card card-two">
            transform
        </div>

        <div class="floating-card card-three">
            animation
        </div>
    </div>
</section>
CSS
@keyframes fadeUp {
    from {
        opacity: 0;

        transform:
            translateY(30px);
    }

    to {
        opacity: 1;

        transform:
            translateY(0);
    }
}

@keyframes orbit {
    to {
        transform:
            rotate(360deg);
    }
}

@keyframes reverseOrbit {
    to {
        transform:
            rotate(-360deg);
    }
}

@keyframes pulseCenter {
    0%,
    100% {
        transform:
            scale(1);

        box-shadow:
            0 0 0 0
            rgba(108, 92, 231, 0.35);
    }

    50% {
        transform:
            scale(1.08);

        box-shadow:
            0 0 0 20px
            rgba(108, 92, 231, 0);
    }
}

@keyframes floatCard {
    from {
        transform:
            translateY(0);
    }

    to {
        transform:
            translateY(-18px);
    }
}

.animation-showcase {
    display: grid;

    grid-template-columns:
        repeat(
            2,
            minmax(0, 1fr)
        );

    gap: 50px;

    align-items: center;

    min-height: 500px;

    padding: 50px;

    overflow: hidden;

    background:
        linear-gradient(
            135deg,
            #f5f6fa,
            #eef0ff
        );

    border-radius: 24px;
}

.showcase-content > * {
    opacity: 0;

    animation:
        fadeUp
        0.8s
        ease
        forwards;
}

.showcase-badge {
    display: inline-block;

    padding: 8px 16px;

    background:
        rgba(108, 92, 231, 0.12);

    color: #6c5ce7;

    border-radius: 999px;

    font-weight: 700;

    animation-delay:
        0.2s;
}

.showcase-content h2 {
    margin:
        20px 0 14px;

    font-size:
        clamp(
            2rem,
            5vw,
            3.5rem
        );

    animation-delay:
        0.4s;
}

.showcase-content p {
    color: #636e72;

    line-height: 1.7;

    animation-delay:
        0.6s;
}

.showcase-button {
    display: inline-flex;

    align-items: center;

    gap: 10px;

    margin-top: 20px;

    padding: 14px 24px;

    border: none;

    background: #6c5ce7;
    color: white;

    border-radius: 10px;

    cursor: pointer;

    animation-delay:
        0.8s;
}

.showcase-button span {
    animation:
        arrowMove
        0.8s
        ease-in-out
        infinite
        alternate;
}

@keyframes arrowMove {
    to {
        transform:
            translateX(6px);
    }
}

.showcase-visual {
    position: relative;

    min-height: 380px;

    display: grid;

    place-items: center;
}

.orbit-ring {
    position: absolute;

    border:
        2px dashed
        rgba(108, 92, 231, 0.3);

    border-radius: 50%;
}

.ring-one {
    width: 260px;
    height: 260px;

    animation:
        orbit
        8s
        linear
        infinite;
}

.ring-two {
    width: 340px;
    height: 340px;

    animation:
        reverseOrbit
        12s
        linear
        infinite;
}

.orbit-ring span {
    position: absolute;

    top: -10px;
    left: 50%;

    width: 20px;
    height: 20px;

    background: #6c5ce7;

    border-radius: 50%;
}

.ring-two span {
    background: #00b894;
}

.center-icon {
    width: 110px;
    height: 110px;

    display: grid;

    place-items: center;

    z-index: 2;

    background: #6c5ce7;
    color: white;

    border-radius: 30px;

    font-size: 3rem;

    animation:
        pulseCenter
        2s
        ease-in-out
        infinite;
}

.floating-card {
    position: absolute;

    z-index: 3;

    padding: 12px 18px;

    background: white;

    border-radius: 10px;

    box-shadow:
        0 12px 30px
        rgba(0, 0, 0, 0.1);

    font-weight: 600;

    animation:
        floatCard
        1.8s
        ease-in-out
        infinite
        alternate;
}

.card-one {
    top: 35px;
    left: 10px;
}

.card-two {
    right: 0;
    top: 130px;

    animation-delay:
        -0.6s;
}

.card-three {
    bottom: 30px;
    left: 50px;

    animation-delay:
        -1.2s;
}

@media (
    max-width: 800px
) {
    .animation-showcase {
        grid-template-columns:
            1fr;
    }
}

@media (
    prefers-reduced-motion:
    reduce
) {
    *,
    *::before,
    *::after {
        animation-duration:
            0.01ms !important;

        animation-iteration-count:
            1 !important;
    }
}

Browser Rendering Flow

When an animation runs, the browser reads the keyframes, calculates progress, determines intermediate values, and renders the current visual state.

Parse @keyframes
Read Animation Properties
Apply Delay
Start Animation Timeline
Calculate Current Progress
Find Surrounding Keyframes
Calculate Intermediate Values
Render Frame
Repeat or Finish
Animation Processing
@keyframes
    │
    ▼
Animation Properties
    │
    ▼
Delay
    │
    ▼
Animation Starts
    │
    ▼
Current Time
    │
    ▼
Calculate Progress %
    │
    ▼
Find Keyframe Values
    │
    ▼
Calculate Intermediate State
    │
    ▼
Render Frame
    │
    ▼
More Time Remaining?
    │
 ┌──┴──┐
 │     │
Yes    No
 │     │
 ▼     ▼
Next   Repeat or
Frame  Finish

Real-World Applications

Loading Indicators

Create spinners, dots, progress effects, and skeleton loaders.

Notifications

Pulse or shake elements to indicate new activity.

Entrance Effects

Fade, slide, or scale content into view.

Attention Effects

Highlight important updates and calls to action.

Illustrations

Animate decorative shapes, icons, and visual scenes.

Data Visualization

Reveal charts, bars, indicators, and changing values.

Text Effects

Create typing, blinking cursor, and reveal animations.

Interactive Interfaces

Animate menus, panels, buttons, cards, and controls.

Advantages

Multi-Step Control

Define many visual states using percentage keyframes.

Automatic Playback

Run animations without requiring user interaction.

Repetition

Repeat animations a fixed number of times or forever.

Direction Control

Play forward, backward, or alternate directions.

Play State

Pause and resume animations.

Fill Modes

Control styles before and after the animation.

Multiple Animations

Run several animation sequences on one element.

JavaScript Integration

Use classes and events to control animation behavior.

Common Beginner Mistakes

Forgetting @keyframes

An animation name must reference a defined keyframe sequence.

Mismatching Animation Names

The animation-name value must match the @keyframes name.

Forgetting animation-duration

The default duration is 0s, so the animation will not visibly run.

Forgetting Time Units

Duration and delay values require units such as s or ms.

Confusing Percentage with Time

Keyframe percentages represent progress through the total duration.

Using infinite Everywhere

Continuous animations can distract users and consume resources.

Confusing Duration and Delay

Duration controls cycle length, while delay controls waiting time.

Reversing Shorthand Time Values

The first time value is duration and the second is delay.

Forgetting animation-fill-mode

The element may return to its original styles after the animation finishes.

Expecting forwards to Repeat

forwards preserves the final state but does not repeat the animation.

Confusing alternate with reverse

reverse always plays backward, while alternate changes direction each cycle.

Animating Too Many Elements

Large numbers of simultaneous animations can reduce performance.

Animating Expensive Properties

Some layout-related properties require more rendering work.

Using Motion Without Purpose

Decorative motion can distract users from important content.

Ignoring Reduced Motion

Some users prefer reduced or removed motion.

Hiding Important Information in Animation

Essential information should remain available when animations are disabled.

Using Extremely Long Durations

Slow animations can make an interface feel unresponsive.

Using Extremely Fast Motion

Very fast movement can be difficult to understand.

Forgetting Mobile Testing

Large animations may overflow or perform differently on smaller devices.

Depending Only on animationend

Animations can be cancelled, removed, or interrupted.

Best Practices

  • Use animations to support meaning and interaction.
  • Avoid motion that distracts from important content.
  • Use transitions for simple two-state changes.
  • Use animations for multi-step or repeating sequences.
  • Give every animation a clear purpose.
  • Use descriptive @keyframes names.
  • Keep animation names consistent.
  • Make sure animation-name matches the @keyframes name.
  • Always provide a duration greater than zero.
  • Use seconds or milliseconds consistently.
  • Remember that 1000ms equals 1s.
  • Keep common interface animations relatively short.
  • Use longer durations only when users need to observe the motion.
  • Use percentage keyframes for multi-step sequences.
  • Use from and to for simple start-to-end animations.
  • Remember that from equals 0%.
  • Remember that to equals 100%.
  • Remember that percentages represent progress, not seconds.
  • Use intermediate keyframes only when they improve the sequence.
  • Avoid unnecessary keyframes.
  • Choose timing functions intentionally.
  • Use ease for general-purpose motion.
  • Use linear for constant-speed movement such as rotation.
  • Use ease-in for accelerating movement.
  • Use ease-out for decelerating movement.
  • Use ease-in-out for smooth starts and endings.
  • Use cubic-bezier() for carefully designed custom motion.
  • Use steps() for discrete frame-like changes.
  • Use animation-delay carefully.
  • Avoid delaying important feedback.
  • Use negative delays when continuous animations need staggered starting positions.
  • Use animation-iteration-count to control repetition.
  • Avoid infinite animation unless repetition is meaningful.
  • Pause or reduce continuous decorative animations when appropriate.
  • Use animation-direction to avoid abrupt resets when suitable.
  • Use alternate for smooth back-and-forth movement.
  • Use reverse only when the sequence should always run backward.
  • Use alternate-reverse when the first cycle should begin backward.
  • Use animation-fill-mode when keyframe styles should apply outside the active animation.
  • Use forwards to preserve the final keyframe state.
  • Use backwards to apply the starting state during delay.
  • Use both when both behaviors are needed.
  • Use animation-play-state for pause and resume behavior.
  • Pause animations when users need time to inspect moving content.
  • Use animation shorthand for concise declarations.
  • Remember that the first shorthand time is duration.
  • Remember that the second shorthand time is delay.
  • Separate multiple animations with commas.
  • Keep multiple animation definitions readable.
  • Avoid combining too many animations on one element.
  • Use transform for visual movement.
  • Use translate() instead of layout changes for simple movement.
  • Use rotate() for spinning and orbital effects.
  • Use scale() for pulse and emphasis effects.
  • Use opacity for fade effects.
  • Combine transform and opacity for entrance animations.
  • Avoid animating width and height when transform can achieve the visual effect.
  • Avoid unnecessary layout-changing animations.
  • Test animation performance on lower-powered devices.
  • Test animations with many elements on the page.
  • Avoid animating very large background areas continuously.
  • Use browser developer tools to inspect animations.
  • Check whether animation-duration is greater than zero.
  • Check whether the keyframe name matches.
  • Check whether another CSS rule overrides the animation.
  • Check shorthand commas when multiple animations fail.
  • Check animation-play-state if an animation appears frozen.
  • Check animation-fill-mode when final styles disappear.
  • Check animation-direction when movement appears reversed.
  • Check animation-iteration-count when repetition is unexpected.
  • Use animation events only when JavaScript truly needs them.
  • Remember that animationiteration fires for repeated cycles.
  • Handle animation cancellation when necessary.
  • Use class changes to trigger animations from JavaScript.
  • Keep JavaScript responsible for state and CSS responsible for visual motion when practical.
  • Avoid manually calculating every animation frame in JavaScript when CSS can handle the effect.
  • Use semantic HTML beneath animated interfaces.
  • Do not depend on animation alone to communicate important information.
  • Use text, icons, labels, or other visual indicators with motion.
  • Respect prefers-reduced-motion.
  • Reduce or remove non-essential animations when requested.
  • Keep functionality available when animation is disabled.
  • Avoid rapid flashing effects.
  • Avoid excessive shaking or large repeated movement.
  • Keep focus indicators visible during animations.
  • Do not animate controls away while users are interacting with them.
  • Keep clickable targets stable.
  • Test hover-triggered animation behavior on touch devices.
  • Test animations on narrow screens.
  • Prevent animated elements from causing unwanted horizontal scrolling.
  • Use overflow carefully around moving elements.
  • Avoid clipping focus indicators.
  • Create consistent motion patterns across a project.
  • Use similar durations for similar types of movement.
  • Use consistent easing curves for related components.
  • Use faster motion for small interface changes.
  • Use slightly longer motion for larger travel distances.
  • Use staggered delays carefully.
  • Avoid making users wait for decorative sequences to finish.
  • Keep loading animations lightweight.
  • Stop loading animations when loading completes.
  • Use infinite rotation with linear timing for common spinners.
  • Use alternate direction for floating effects.
  • Use fill-mode both for many entrance animations with delays.
  • Use steps() for typing and sprite-like effects.
  • Keep animation code organized near the components that use it.
  • Reuse keyframes when several elements share the same motion.
  • Create separate keyframes when motion behavior is meaningfully different.
  • Avoid changing too many unrelated properties inside one animation.
  • Choose the simplest animation that solves the visual requirement.
  • Keep animations smooth, accessible, performant, and purposeful.
Remember the Animation Formula

Define the sequence with @keyframes, connect it using animation-name, set the duration, and then control timing, delay, repetition, direction, fill behavior, and play state.

Frequently Asked Questions

What is CSS Animation?

CSS Animation allows elements to change through one or more visual states over time using @keyframes and animation properties.

What is @keyframes?

@keyframes defines the important states of a CSS animation.

What does from mean?

from represents the beginning of the animation and is equivalent to 0%.

What does to mean?

to represents the end of the animation and is equivalent to 100%.

Can an animation have more than two states?

Yes. Percentage keyframes can define any number of intermediate states.

Do keyframe percentages represent seconds?

No. They represent progress through the total animation duration.

What does animation-name do?

It connects an element to a named @keyframes rule.

What does animation-duration do?

It defines how long one complete animation cycle takes.

What is the default animation duration?

The default duration is 0s.

What does animation-timing-function do?

It controls how animation speed changes between keyframes.

What does animation-delay do?

It defines how long the browser waits before starting the animation.

Can animation-delay be negative?

Yes. A negative delay starts the animation immediately from a later point in its timeline.

What does animation-iteration-count do?

It defines how many times an animation repeats.

How do I repeat an animation forever?

Use animation-iteration-count: infinite.

Can iteration count use decimal values?

Yes. A value such as 0.5 runs half of one animation cycle.

What does animation-direction do?

It controls whether animation cycles play forward, backward, or alternate directions.

What is the difference between reverse and alternate?

reverse plays every cycle backward, while alternate changes direction after each cycle.

What does animation-fill-mode do?

It controls which keyframe styles apply before the animation starts and after it ends.

What does forwards do?

forwards preserves the final keyframe styles after the animation finishes.

What does backwards do?

backwards applies the starting keyframe styles during the animation delay.

What does both do?

both combines the behavior of forwards and backwards.

What does animation-play-state do?

It controls whether an animation is running or paused.

Can I pause an animation on hover?

Yes. Set animation-play-state: paused inside the :hover rule.

Can one element have multiple animations?

Yes. Separate multiple animation definitions with commas.

What is the animation shorthand?

It combines animation name, duration, timing function, delay, iteration count, direction, fill mode, and play state.

Which shorthand time value is duration?

The first time value is the animation duration.

Which shorthand time value is delay?

The second time value is the animation delay.

Can CSS animations start automatically?

Yes. They can start automatically when the animation styles are applied.

Can JavaScript control CSS animations?

Yes. JavaScript can add classes, change animation properties, pause animations, and listen for animation events.

What is animationstart?

It is an event that fires when an animation begins.

What is animationiteration?

It is an event that fires when a repeating animation completes a cycle and begins another.

What is animationend?

It is an event that fires when a finite animation finishes.

Which properties are commonly good for animation performance?

transform and opacity are commonly preferred for many visual animation effects.

Should every animation use infinite?

No. Infinite animation should be used only when continuous repetition serves a clear purpose.

What is prefers-reduced-motion?

It is a media feature that allows CSS to reduce or remove motion when the user prefers less animation.

What is the difference between CSS transition and animation?

A transition usually handles a change between states, while an animation can define multiple keyframes, run automatically, repeat, reverse, and pause.

When should I use transition?

Use transitions for simple state changes such as hover, focus, and class changes.

When should I use animation?

Use animations for multi-step sequences, automatic playback, repetition, loaders, entrance effects, and complex motion.

What comes after CSS Animation?

The next lesson covers CSS Media Queries, including responsive design, breakpoints, viewport conditions, mobile-first design, desktop-first design, orientation, media features, and practical responsive layouts.

Key Takeaways

  • CSS animations create visual sequences over time.
  • @keyframes defines the animation states.
  • from is equivalent to 0%.
  • to is equivalent to 100%.
  • Percentage keyframes create multi-step animations.
  • Keyframe percentages represent progress through the total duration.
  • animation-name selects the keyframe sequence.
  • animation-duration defines one cycle length.
  • The default duration is 0s.
  • animation-timing-function controls speed changes.
  • animation-delay controls when the animation starts.
  • Negative delays start partway through the animation.
  • animation-iteration-count controls repetition.
  • infinite repeats the animation continuously.
  • animation-direction controls playback direction.
  • normal plays forward.
  • reverse plays backward.
  • alternate changes direction each cycle.
  • alternate-reverse begins backward and alternates.
  • animation-fill-mode controls styles outside the active animation.
  • forwards keeps the final state.
  • backwards applies the starting state during delay.
  • both combines forwards and backwards.
  • animation-play-state can pause and resume animations.
  • Multiple animations are separated with commas.
  • The animation shorthand combines animation settings.
  • The first shorthand time is duration.
  • The second shorthand time is delay.
  • Transform and opacity are commonly useful for smooth animation.
  • Animation events allow JavaScript to react to animation activity.
  • prefers-reduced-motion helps respect user motion preferences.
  • Animations should be purposeful, accessible, and performant.

Summary

CSS Animation allows elements to move through one or more visual states over time.

The @keyframes rule defines the important states of an animation.

Simple animations can use from and to, while complex animations can use percentage keyframes.

The animation-name property connects an element to a named keyframe sequence.

The animation-duration property defines how long one complete cycle takes.

The animation-timing-function property controls how speed changes between keyframes.

The animation-delay property controls how long the browser waits before the animation begins.

The animation-iteration-count property defines how many times the animation repeats.

The infinite keyword creates continuously repeating animations.

The animation-direction property controls whether cycles play forward, backward, or alternate directions.

The animation-fill-mode property controls which keyframe styles apply before and after the animation.

The animation-play-state property can run or pause an animation.

The animation shorthand combines the animation name, duration, timing function, delay, iteration count, direction, fill mode, and play state.

Multiple animations can run on one element by separating animation definitions with commas.

Transform and opacity are commonly used for movement, rotation, scaling, fading, loaders, entrance effects, and interactive motion.

JavaScript can control CSS animations using classes, styles, and animation events.

For accessible interfaces, non-essential animations should be reduced or removed when the user prefers reduced motion.

CSS animations are ideal for loaders, notifications, entrance effects, decorative illustrations, typing effects, repeating movement, and complex multi-step visual sequences.

In the next lesson, you will learn CSS Media Queries, including responsive design, breakpoints, viewport widths, mobile-first design, desktop-first design, orientation, media features, and complete responsive layout examples.