|

CSS 55 ๐Ÿ’ป animation property

The animation property is one of the most powerful tools in CSS. It lets you create complex, multi-step animations โ€” with full control over timing, repetition, direction, and more.


What is an Animation?

An animation in CSS is defined by two parts:

  1. @keyframes โ€” defines the stages of the animation
  2. animation property โ€” applies the animation to an element

Unlike transitions (which animate between two states), animations can have many stages and run automatically without user interaction.


The animation Shorthand

The animation property is a shorthand for 8 individual animation properties:

PropertyDescriptionDefault
animation-nameName of the @keyframes rulenone
animation-durationHow long one cycle takes0s
animation-timing-functionSpeed curveease
animation-delayWait before starting0s
animation-iteration-countHow many times to repeat1
animation-directionDirection of each cyclenormal
animation-fill-modeStyles before/after animationnone
animation-play-stateRunning or pausedrunning

Syntax

animation: name duration timing-function delay iteration-count direction fill-mode play-state;

Only name and duration are required. All other values are optional.


The @keyframes Rule

The @keyframes rule defines the stages of an animation.

@keyframes exampleAnimation {
    0%   { background-color: red; transform: scale(1); }
    50%  { background-color: blue; transform: scale(1.5); }
    100% { background-color: green; transform: scale(1); }
}

Syntax Options

Using from and to:

@keyframes fadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

Using percentages:

@keyframes bounce {
    0%   { transform: translateY(0); }
    50%  { transform: translateY(-50px); }
    100% { transform: translateY(0); }
}
KeywordEquivalent
from0%
to100%

Individual Animation Properties

1. animation-name

The name of the @keyframes rule to use.

animation-name: exampleAnimation;

2. animation-duration

How long one cycle of the animation takes.

animation-duration: 4s;

3. animation-timing-function

The speed curve of the animation.

animation-timing-function: ease-in-out;
ValueDescription
easeSlow start, fast middle, slow end (default)
linearConstant speed
ease-inSlow start, fast end
ease-outFast start, slow end
ease-in-outSlow start, fast middle, slow end
cubic-bezier(n,n,n,n)Custom curve
steps(n)Stepped animation

4. animation-delay

How long to wait before starting the animation.

animation-delay: 2s;

5. animation-iteration-count

How many times the animation repeats.

animation-iteration-count: infinite; /* or a number */
ValueDescription
1Plays once (default)
3Plays 3 times
infiniteRepeats forever

6. animation-direction

The direction of each cycle.

animation-direction: alternate;
ValueDescription
normalForward each cycle (default)
reverseBackward each cycle
alternateForward, then backward
alternate-reverseBackward, then forward

7. animation-fill-mode

What styles apply before and after the animation.

animation-fill-mode: forwards;
ValueDescription
noneNo styles applied outside the animation (default)
forwardsKeep the last keyframe’s styles
backwardsApply the first keyframe’s styles during delay
bothApply both forwards and backwards

8. animation-play-state

Whether the animation is running or paused.

animation-play-state: paused;
ValueDescription
runningAnimation is playing (default)
pausedAnimation is paused

Complete Example

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>The animation Property</title>
    <style>
        *, *::before, *::after {
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            padding: 20px;
            background: #f8f9fa;
            color: #333;
            max-width: 1200px;
            margin: 0 auto;
            line-height: 1.6;
        }

        h1 {
            color: #007bff;
            border-bottom: 3px solid #007bff;
            padding-bottom: 10px;
        }

        h2 {
            color: #28a745;
            border-left: 4px solid #28a745;
            padding-left: 15px;
            margin-top: 30px;
        }

        h3 {
            color: #333;
            margin-top: 20px;
        }

        section {
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            margin: 20px 0;
        }

        .code-block {
            background: #1e1e1e;
            color: #d4d4d4;
            padding: 15px;
            border-radius: 8px;
            overflow-x: auto;
            font-family: 'Courier New', monospace;
            font-size: 0.9rem;
            line-height: 1.8;
            margin: 10px 0;
        }

        .reference-table {
            width: 100%;
            border-collapse: collapse;
            margin: 15px 0;
        }

        .reference-table th,
        .reference-table td {
            padding: 10px;
            border: 1px solid #ddd;
            text-align: left;
        }

        .reference-table th {
            background: #007bff;
            color: white;
        }

        .reference-table tr:nth-child(even) {
            background: #f8f9fa;
        }

        .note {
            font-size: 0.9rem;
            color: #6c757d;
            margin-top: 5px;
        }

        .highlight {
            background: #ffc107;
            color: #333;
            padding: 2px 6px;
            border-radius: 4px;
            font-weight: bold;
        }

        /* ====== DEMO AREA ====== */
        .demo-area {
            display: flex;
            flex-wrap: wrap;
            gap: 40px;
            justify-content: center;
            align-items: center;
            padding: 40px 20px;
            background: #e9ecef;
            border-radius: 8px;
            margin: 15px 0;
            min-height: 200px;
            overflow: hidden;
        }

        /* ====== BASIC ANIMATION ====== */
        .animation-example {
            width: 100px;
            height: 100px;
            background-color: #dc3545;
            border-radius: 12px;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
            animation-name: exampleAnimation;
            animation-duration: 4s;
            animation-timing-function: ease-in-out;
            animation-delay: 2s;
            animation-iteration-count: infinite;
        }

        @keyframes exampleAnimation {
            0%   { background-color: #dc3545; transform: scale(1); }
            50%  { background-color: #007bff; transform: scale(1.5); }
            100% { background-color: #28a745; transform: scale(1); }
        }

        /* ====== SHORTHAND ====== */
        .animation-shorthand {
            width: 100px;
            height: 100px;
            background: #6c5ce7;
            border-radius: 12px;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
            animation: bounce 2s ease-in-out infinite;
        }

        @keyframes bounce {
            0%, 100% { transform: translateY(0); }
            50%      { transform: translateY(-40px); }
        }

        /* ====== FADE IN ====== */
        .fade-in {
            width: 100px;
            height: 100px;
            background: #28a745;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: bold;
            animation: fadeIn 2s ease forwards;
            opacity: 0;
        }

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

        /* ====== SLIDE IN ====== */
        .slide-in {
            width: 100px;
            height: 100px;
            background: #ffc107;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: #333;
            font-weight: bold;
            animation: slideIn 1.5s ease-out forwards;
            transform: translateX(-200px);
        }

        @keyframes slideIn {
            from { transform: translateX(-200px); }
            to   { transform: translateX(0); }
        }

        /* ====== PULSE ====== */
        .pulse {
            width: 100px;
            height: 100px;
            background: #dc3545;
            border-radius: 50%;
            animation: pulse 1.5s ease-in-out infinite;
        }

        @keyframes pulse {
            0%   { transform: scale(1); box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.7); }
            70%  { transform: scale(1.1); box-shadow: 0 0 0 20px rgba(220, 53, 69, 0); }
            100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(220, 53, 69, 0); }
        }

        /* ====== ROTATE ====== */
        .rotate {
            width: 100px;
            height: 100px;
            background: #17a2b8;
            border-radius: 12px;
            animation: rotate 3s linear infinite;
        }

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

        /* ====== SPINNER ====== */
        .spinner {
            width: 60px;
            height: 60px;
            border: 6px solid #e9ecef;
            border-top: 6px solid #007bff;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

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

        /* ====== MULTI-STEP ====== */
        .multi-step {
            width: 100px;
            height: 100px;
            background: #007bff;
            border-radius: 12px;
            animation: multiStep 4s ease-in-out infinite;
        }

        @keyframes multiStep {
            0%   { background: #007bff; transform: translate(0, 0) rotate(0deg); }
            25%  { background: #28a745; transform: translate(100px, 0) rotate(90deg); }
            50%  { background: #ffc107; transform: translate(100px, 100px) rotate(180deg); }
            75%  { background: #dc3545; transform: translate(0, 100px) rotate(270deg); }
            100% { background: #007bff; transform: translate(0, 0) rotate(360deg); }
        }

        /* ====== DIRECTION COMPARISON ====== */
        .direction-box {
            width: 80px;
            height: 80px;
            background: #6c5ce7;
            border-radius: 12px;
            animation-duration: 2s;
            animation-timing-function: ease-in-out;
            animation-iteration-count: infinite;
        }

        .direction-normal {
            animation-name: slideAcross;
            animation-direction: normal;
        }

        .direction-reverse {
            animation-name: slideAcross;
            animation-direction: reverse;
        }

        .direction-alternate {
            animation-name: slideAcross;
            animation-direction: alternate;
        }

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

        @keyframes slideAcross {
            from { transform: translateX(0); background: #6c5ce7; }
            to   { transform: translateX(150px); background: #28a745; }
        }

        /* ====== FILL MODE COMPARISON ====== */
        .fill-box {
            width: 80px;
            height: 80px;
            background: #007bff;
            border-radius: 12px;
            animation-duration: 2s;
            animation-delay: 1s;
            animation-timing-function: ease;
            animation-fill-mode: none;
            animation-name: fillDemo;
            opacity: 0;
        }

        .fill-none {
            animation-fill-mode: none;
        }

        .fill-forwards {
            animation-fill-mode: forwards;
        }

        .fill-backwards {
            animation-fill-mode: backwards;
        }

        .fill-both {
            animation-fill-mode: both;
        }

        @keyframes fillDemo {
            from { opacity: 0; transform: translateX(-50px); background: #dc3545; }
            to   { opacity: 1; transform: translateX(0); background: #28a745; }
        }

        /* ====== PLAY STATE ====== */
        .play-pause-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 15px;
        }

        .play-pause-box {
            width: 100px;
            height: 100px;
            background: #ffc107;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: #333;
            font-weight: bold;
            animation: pulse 1.5s ease-in-out infinite;
        }

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

        /* ====== PRACTICAL: LOADING SKELETON ====== */
        .skeleton-container {
            max-width: 400px;
            margin: 15px auto;
            padding: 20px;
            background: white;
            border-radius: 12px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        }

        .skeleton-line {
            height: 16px;
            background: linear-gradient(90deg, #e9ecef 25%, #f8f9fa 50%, #e9ecef 75%);
            background-size: 200% 100%;
            border-radius: 8px;
            margin-bottom: 12px;
            animation: shimmer 1.5s infinite;
        }

        .skeleton-line.short {
            width: 60%;
        }

        @keyframes shimmer {
            0%   { background-position: 200% 0; }
            100% { background-position: -200% 0; }
        }

        /* ====== PRACTICAL: BUTTON LOADING ====== */
        .btn-loading {
            padding: 15px 35px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 8px;
            font-size: 1em;
            font-weight: bold;
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            gap: 10px;
            margin: 10px;
        }

        .btn-loading .dot {
            width: 8px;
            height: 8px;
            background: white;
            border-radius: 50%;
            animation: dotPulse 1.4s ease-in-out infinite;
        }

        .btn-loading .dot:nth-child(2) {
            animation-delay: 0.2s;
        }

        .btn-loading .dot:nth-child(3) {
            animation-delay: 0.4s;
        }

        @keyframes dotPulse {
            0%, 80%, 100% { transform: scale(0.6); opacity: 0.5; }
            40%           { transform: scale(1); opacity: 1; }
        }

        /* ====== PRACTICAL: FLOATING ELEMENTS ====== */
        .float-container {
            display: flex;
            gap: 30px;
            justify-content: center;
            margin: 20px 0;
        }

        .float-item {
            width: 80px;
            height: 80px;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 2rem;
            animation: float 3s ease-in-out infinite;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
        }

        .float-item:nth-child(1) { background: #007bff; animation-delay: 0s; }
        .float-item:nth-child(2) { background: #28a745; animation-delay: 0.3s; }
        .float-item:nth-child(3) { background: #ffc107; animation-delay: 0.6s; }
        .float-item:nth-child(4) { background: #dc3545; animation-delay: 0.9s; }

        @keyframes float {
            0%, 100% { transform: translateY(0); }
            50%      { transform: translateY(-20px); }
        }

        /* ====== TIPS ====== */
        .tip-box {
            padding: 15px;
            border-radius: 8px;
            margin: 10px 0;
            border-left: 4px solid #007bff;
            background: #f8f9fa;
        }

        .tip-box.success { border-left-color: #28a745; }
        .tip-box.warning { border-left-color: #ffc107; }
        .tip-box.danger { border-left-color: #dc3545; }
    </style>
</head>
<body>

    <h1>The animation Property</h1>

    <!-- ====== 1. BASIC ANIMATION ====== -->
    <section>
        <h2>1. Basic Animation</h2>
        <p>This box animates through three colors and scales using all individual properties.</p>

        <div class="demo-area">
            <div class="animation-example"></div>
        </div>

        <div class="code-block">
            .animation-example {
                animation-name: exampleAnimation;
                animation-duration: 4s;
                animation-timing-function: ease-in-out;
                animation-delay: 2s;
                animation-iteration-count: infinite;
            }

            @keyframes exampleAnimation {
                0%   { background-color: red; transform: scale(1); }
                50%  { background-color: blue; transform: scale(1.5); }
                100% { background-color: green; transform: scale(1); }
            }
        </div>
    </section>

    <!-- ====== 2. SHORTHAND ====== -->
    <section>
        <h2>2. animation Shorthand</h2>
        <p>The shorthand combines all animation properties into one declaration.</p>

        <div class="demo-area">
            <div class="animation-shorthand"></div>
        </div>

        <div class="code-block">
            /* Shorthand: name duration timing-function delay iteration-count direction fill-mode play-state */
            .animation-shorthand {
                animation: bounce 2s ease-in-out infinite;
            }

            @keyframes bounce {
                0%, 100% { transform: translateY(0); }
                50%      { transform: translateY(-40px); }
            }
        </div>
    </section>

    <!-- ====== 3. COMMON ANIMATIONS ====== -->
    <section>
        <h2>3. Common Animation Patterns</h2>

        <h3>Fade In</h3>
        <div class="demo-area">
            <div class="fade-in">Fade In</div>
        </div>
        <div class="code-block">
            .fade-in {
                animation: fadeIn 2s ease forwards;
                opacity: 0;
            }

            @keyframes fadeIn {
                from { opacity: 0; transform: translateY(20px); }
                to   { opacity: 1; transform: translateY(0); }
            }
        </div>

        <h3>Slide In</h3>
        <div class="demo-area">
            <div class="slide-in">Slide In</div>
        </div>
        <div class="code-block">
            .slide-in {
                animation: slideIn 1.5s ease-out forwards;
                transform: translateX(-200px);
            }

            @keyframes slideIn {
                from { transform: translateX(-200px); }
                to   { transform: translateX(0); }
            }
        </div>

        <h3>Pulse</h3>
        <div class="demo-area">
            <div class="pulse"></div>
        </div>
        <div class="code-block">
            .pulse {
                animation: pulse 1.5s ease-in-out infinite;
            }

            @keyframes pulse {
                0%   { transform: scale(1); box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.7); }
                70%  { transform: scale(1.1); box-shadow: 0 0 0 20px rgba(220, 53, 69, 0); }
                100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(220, 53, 69, 0); }
            }
        </div>

        <h3>Rotate</h3>
        <div class="demo-area">
            <div class="rotate"></div>
        </div>
        <div class="code-block">
            .rotate {
                animation: rotate 3s linear infinite;
            }

            @keyframes rotate {
                from { transform: rotate(0deg); }
                to   { transform: rotate(360deg); }
            }
        </div>

        <h3>Spinner</h3>
        <div class="demo-area">
            <div class="spinner"></div>
        </div>
        <div class="code-block">
            .spinner {
                border: 6px solid #e9ecef;
                border-top: 6px solid #007bff;
                border-radius: 50%;
                animation: spin 1s linear infinite;
            }

            @keyframes spin {
                to { transform: rotate(360deg); }
            }
        </div>
    </section>

    <!-- ====== 4. MULTI-STEP ANIMATION ====== -->
    <section>
        <h2>4. Multi-Step Animation</h2>
        <p>This box travels in a square pattern using multiple keyframes.</p>

        <div class="demo-area" style="min-height: 300px;">
            <div class="multi-step"></div>
        </div>

        <div class="code-block">
            .multi-step {
                animation: multiStep 4s ease-in-out infinite;
            }

            @keyframes multiStep {
                0%   { background: #007bff; transform: translate(0, 0) rotate(0deg); }
                25%  { background: #28a745; transform: translate(100px, 0) rotate(90deg); }
                50%  { background: #ffc107; transform: translate(100px, 100px) rotate(180deg); }
                75%  { background: #dc3545; transform: translate(0, 100px) rotate(270deg); }
                100% { background: #007bff; transform: translate(0, 0) rotate(360deg); }
            }
        </div>
    </section>

    <!-- ====== 5. ANIMATION DIRECTION ====== -->
    <section>
        <h2>5. animation-direction</h2>
        <p>Compare the four direction values.</p>

        <div class="demo-area" style="flex-direction: column; gap: 20px; align-items: flex-start;">
            <div style="display: flex; align-items: center; gap: 20px;">
                <span style="font-weight: bold; min-width: 180px;">normal:</span>
                <div class="direction-box direction-normal"></div>
            </div>
            <div style="display: flex; align-items: center; gap: 20px;">
                <span style="font-weight: bold; min-width: 180px;">reverse:</span>
                <div class="direction-box direction-reverse"></div>
            </div>
            <div style="display: flex; align-items: center; gap: 20px;">
                <span style="font-weight: bold; min-width: 180px;">alternate:</span>
                <div class="direction-box direction-alternate"></div>
            </div>
            <div style="display: flex; align-items: center; gap: 20px;">
                <span style="font-weight: bold; min-width: 180px;">alternate-reverse:</span>
                <div class="direction-box direction-alternate-reverse"></div>
            </div>
        </div>

        <div class="code-block">
            .direction-normal           { animation-direction: normal; }
            .direction-reverse          { animation-direction: reverse; }
            .direction-alternate        { animation-direction: alternate; }
            .direction-alternate-reverse { animation-direction: alternate-reverse; }

            @keyframes slideAcross {
                from { transform: translateX(0); background: #6c5ce7; }
                to   { transform: translateX(150px); background: #28a745; }
            }
        </div>
    </section>

    <!-- ====== 6. ANIMATION FILL MODE ====== -->
    <section>
        <h2>6. animation-fill-mode</h2>
        <p>Compare how styles apply before and after the animation.</p>

        <div class="demo-area" style="flex-direction: column; gap: 20px; align-items: flex-start;">
            <div style="display: flex; align-items: center; gap: 20px;">
                <span style="font-weight: bold; min-width: 150px;">none:</span>
                <div class="fill-box fill-none"></div>
            </div>
            <div style="display: flex; align-items: center; gap: 20px;">
                <span style="font-weight: bold; min-width: 150px;">forwards:</span>
                <div class="fill-box fill-forwards"></div>
            </div>
            <div style="display: flex; align-items: center; gap: 20px;">
                <span style="font-weight: bold; min-width: 150px;">backwards:</span>
                <div class="fill-box fill-backwards"></div>
            </div>
            <div style="display: flex; align-items: center; gap: 20px;">
                <span style="font-weight: bold; min-width: 150px;">both:</span>
                <div class="fill-box fill-both"></div>
            </div>
        </div>

        <div class="code-block">
            .fill-none      { animation-fill-mode: none; }
            .fill-forwards  { animation-fill-mode: forwards; }
            .fill-backwards { animation-fill-mode: backwards; }
            .fill-both      { animation-fill-mode: both; }

            @keyframes fillDemo {
                from { opacity: 0; transform: translateX(-50px); background: #dc3545; }
                to   { opacity: 1; transform: translateX(0); background: #28a745; }
            }
        </div>

        <p class="note"><strong>forwards</strong> keeps the end state, <strong>backwards</strong> applies the start state during delay, and <strong>both</strong> does both.</p>
    </section>

    <!-- ====== 7. ANIMATION PLAY STATE ====== -->
    <section>
        <h2>7. animation-play-state</h2>
        <p>Hover over the box to pause the animation.</p>

        <div class="demo-area">
            <div class="play-pause-container">
                <div class="play-pause-box">Hover to Pause</div>
            </div>
        </div>

        <div class="code-block">
            .play-pause-box {
                animation: pulse 1.5s ease-in-out infinite;
            }

            .play-pause-box:hover {
                animation-play-state: paused;
            }
        </div>
    </section>

    <!-- ====== 8. PRACTICAL: LOADING SKELETON ====== -->
    <section>
        <h2>8. Practical Example: Loading Skeleton</h2>
        <p>A shimmer effect commonly used in loading placeholders.</p>

        <div class="skeleton-container">
            <div class="skeleton-line"></div>
            <div class="skeleton-line"></div>
            <div class="skeleton-line short"></div>
        </div>

        <div class="code-block">
            .skeleton-line {
                background: linear-gradient(90deg, #e9ecef 25%, #f8f9fa 50%, #e9ecef 75%);
                background-size: 200% 100%;
                animation: shimmer 1.5s infinite;
            }

            @keyframes shimmer {
                0%   { background-position: 200% 0; }
                100% { background-position: -200% 0; }
            }
        </div>
    </section>

    <!-- ====== 9. PRACTICAL: BUTTON LOADING ====== -->
    <section>
        <h2>9. Practical Example: Button Loading Dots</h2>
        <p>Animated dots for a loading button.</p>

        <div style="text-align: center;">
            <button class="btn-loading">
                Loading
                <span class="dot"></span>
                <span class="dot"></span>
                <span class="dot"></span>
            </button>
        </div>

        <div class="code-block">
            .btn-loading .dot {
                width: 8px;
                height: 8px;
                background: white;
                border-radius: 50%;
                animation: dotPulse 1.4s ease-in-out infinite;
            }

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

            @keyframes dotPulse {
                0%, 80%, 100% { transform: scale(0.6); opacity: 0.5; }
                40%           { transform: scale(1); opacity: 1; }
            }
        </div>
    </section>

    <!-- ====== 10. PRACTICAL: FLOATING ELEMENTS ====== -->
    <section>
        <h2>10. Practical Example: Floating Elements</h2>
        <p>Staggered floating animation with different delays.</p>

        <div class="float-container">
            <div class="float-item">๐Ÿš€</div>
            <div class="float-item">โญ</div>
            <div class="float-item">๐ŸŽฏ</div>
            <div class="float-item">๐Ÿ’Ž</div>
        </div>

        <div class="code-block">
            .float-item {
                animation: float 3s ease-in-out infinite;
            }

            .float-item:nth-child(1) { animation-delay: 0s; }
            .float-item:nth-child(2) { animation-delay: 0.3s; }
            .float-item:nth-child(3) { animation-delay: 0.6s; }
            .float-item:nth-child(4) { animation-delay: 0.9s; }

            @keyframes float {
                0%, 100% { transform: translateY(0); }
                50%      { transform: translateY(-20px); }
            }
        </div>
    </section>

    <!-- ====== 11. REFERENCE TABLES ====== -->
    <section>
        <h2>11. Reference Tables</h2>

        <h3>Animation Properties</h3>
        <table class="reference-table">
            <tr>
                <th>Property</th>
                <th>Description</th>
                <th>Default</th>
            </tr>
            <tr>
                <td><code>animation-name</code></td>
                <td>Name of the @keyframes rule</td>
                <td><code>none</code></td>
            </tr>
            <tr>
                <td><code>animation-duration</code></td>
                <td>How long one cycle takes</td>
                <td><code>0s</code></td>
            </tr>
            <tr>
                <td><code>animation-timing-function</code></td>
                <td>Speed curve</td>
                <td><code>ease</code></td>
            </tr>
            <tr>
                <td><code>animation-delay</code></td>
                <td>Wait before starting</td>
                <td><code>0s</code></td>
            </tr>
            <tr>
                <td><code>animation-iteration-count</code></td>
                <td>How many times to repeat</td>
                <td><code>1</code></td>
            </tr>
            <tr>
                <td><code>animation-direction</code></td>
                <td>Direction of each cycle</td>
                <td><code>normal</code></td>
            </tr>
            <tr>
                <td><code>animation-fill-mode</code></td>
                <td>Styles before/after animation</td>
                <td><code>none</code></td>
            </tr>
            <tr>
                <td><code>animation-play-state</code></td>
                <td>Running or paused</td>
                <td><code>running</code></td>
            </tr>
        </table>

        <h3>animation-direction Values</h3>
        <table class="reference-table">
            <tr>
                <th>Value</th>
                <th>Description</th>
            </tr>
            <tr>
                <td><code>normal</code></td>
                <td>Forward each cycle (default)</td>
            </tr>
            <tr>
                <td><code>reverse</code></td>
                <td>Backward each cycle</td>
            </tr>
            <tr>
                <td><code>alternate</code></td>
                <td>Forward, then backward</td>
            </tr>
            <tr>
                <td><code>alternate-reverse</code></td>
                <td>Backward, then forward</td>
            </tr>
        </table>

        <h3>animation-fill-mode Values</h3>
        <table class="reference-table">
            <tr>
                <th>Value</th>
                <th>Description</th>
            </tr>
            <tr>
                <td><code>none</code></td>
                <td>No styles applied outside the animation (default)</td>
            </tr>
            <tr>
                <td><code>forwards</code></td>
                <td>Keep the last keyframe's styles</td>
            </tr>
            <tr>
                <td><code>backwards</code></td>
                <td>Apply the first keyframe's styles during delay</td>
            </tr>
            <tr>
                <td><code>both</code></td>
                <td>Apply both forwards and backwards</td>
            </tr>
        </table>

        <h3>@keyframes Syntax</h3>
        <table class="reference-table">
            <tr>
                <th>Syntax</th>
                <th>Description</th>
            </tr>
            <tr>
                <td><code>from { }</code></td>
                <td>Equivalent to <code>0%</code></td>
            </tr>
            <tr>
                <td><code>to { }</code></td>
                <td>Equivalent to <code>100%</code></td>
            </tr>
            <tr>
                <td><code>50% { }</code></td>
                <td>Halfway through the animation</td>
            </tr>
        </table>
    </section>

    <!-- ====== 12. BEST PRACTICES ====== -->
    <section>
        <h2>12. Best Practices</h2>

        <div style="background: #d4edda; padding: 20px; border-radius: 8px; border-left: 4px solid #28a745;">
            <h3 style="margin-top: 0; color: #155724;">โœ… Do This:</h3>
            <ul>
                <li>Use <code>transform</code> and <code>opacity</code> for smooth, hardware-accelerated animations</li>
                <li>Use the shorthand <code>animation</code> for cleaner code</li>
                <li>Use <code>animation-fill-mode: forwards</code> to keep the end state</li>
                <li>Use <code>animation-delay</code> for staggered effects</li>
                <li>Use <code>infinite</code> for continuous animations (loading spinners)</li>
                <li>Respect <code>prefers-reduced-motion</code> for accessibility</li>
                <li>Keep animations short and purposeful</li>
            </ul>
        </div>

        <div style="background: #f8d7da; padding: 20px; border-radius: 8px; border-left: 4px solid #dc3545; margin-top: 15px;">
            <h3 style="margin-top: 0; color: #721c24;">โŒ Don't Do This:</h3>
            <ul>
                <li>Don't animate layout properties (<code>width</code>, <code>height</code>, <code>top</code>, <code>left</code>)</li>
                <li>Don't use <code>infinite</code> animations that distract from content</li>
                <li>Don't forget to specify <code>animation-duration</code> (default is 0s โ€” no animation!)</li>
                <li>Don't use animations for critical functionality that must work without them</li>
                <li>Don't overuse animations โ€” a few well-placed ones are better than many</li>
                <li>Don't forget about <code>prefers-reduced-motion</code></li>
            </ul>
        </div>

        <div class="code-block">
            /* Accessibility: respect reduced motion */
            @media (prefers-reduced-motion: reduce) {
                .animation-example,
                .bounce,
                .pulse,
                .rotate,
                .spinner,
                .float-item {
                    animation: none;
                }
            }

            /* Best practice: use transform and opacity */
            .smooth {
                animation: slideIn 1s ease forwards;
            }

            @keyframes slideIn {
                from { opacity: 0; transform: translateY(20px); }
                to   { opacity: 1; transform: translateY(0); }
            }
        </div>
    </section>

</body>
</html>

Quick Reference

PropertyDescriptionDefault
animation-nameName of the @keyframes rulenone
animation-durationHow long one cycle takes0s
animation-timing-functionSpeed curveease
animation-delayWait before starting0s
animation-iteration-countHow many times to repeat1
animation-directionDirection of each cyclenormal
animation-fill-modeStyles before/after animationnone
animation-play-stateRunning or pausedrunning

animation-direction Values

ValueDescription
normalForward each cycle (default)
reverseBackward each cycle
alternateForward, then backward
alternate-reverseBackward, then forward

animation-fill-mode Values

ValueDescription
noneNo styles applied outside the animation (default)
forwardsKeep the last keyframe’s styles
backwardsApply the first keyframe’s styles during delay
bothApply both forwards and backwards

@keyframes Syntax

SyntaxDescription
from { }Equivalent to 0%
to { }Equivalent to 100%
50% { }Halfway through the animation

Best Practices

โœ… Do This:

/* Simple bounce animation */
.bounce {
    animation: bounce 1s ease infinite;
}

@keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-20px); }
}

/* Fade in and stay visible */
.fade-in {
    animation: fadeIn 1s ease forwards;
    opacity: 0;
}

@keyframes fadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Staggered animation */
.item:nth-child(1) { animation-delay: 0s; }
.item:nth-child(2) { animation-delay: 0.1s; }
.item:nth-child(3) { animation-delay: 0.2s; }

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
    .bounce, .fade-in {
        animation: none;
    }
}

โŒ Don’t Do This:

/* Don't forget animation-duration */
.box {
    animation-name: bounce; /* Duration is 0s by default โ€” no animation! */
}

/* Don't animate layout properties */
.box {
    animation: moveBox 1s infinite;
}
@keyframes moveBox {
    from { left: 0; }
    to   { left: 100px; } /* Causes layout recalculation */
}

/* Don't overuse infinite animations */
.everything {
    animation: spin 1s infinite; /* Distracting */
}

Pro Tip: CSS animations are perfect for attention-grabbing effects (loading spinners, notifications), entrance animations (fade in, slide in), and continuous ambient effects (floating, pulsing). Use transform and opacity for the smoothest animations โ€” they’re hardware-accelerated. Remember: animation-duration is required (default 0s means no animation). Use animation-fill-mode: forwards to keep the end state. And always respect prefers-reduced-motion โ€” some users are sensitive to motion and may experience discomfort from animations!


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!