|

CSS 56 💻 animation properties part 1

This lesson covers six essential animation properties: animation-name, animation-duration, animation-timing-function, animation-delay, animation-iteration-count, and animation-direction.


Overview of 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

1. animation-name

Specifies the name of the @keyframes rule that defines the animation.

.box {
    animation-name: slideIn;
}
ValueDescription
noneNo animation (default)
custom-nameName of a @keyframes rule
MultipleComma-separated list

Multiple animations:

.box {
    animation-name: slideIn, fadeIn;
    animation-duration: 2s, 1s;
}

2. animation-duration

Specifies the length of time for one animation cycle.

.box {
    animation-duration: 2s;
}
ValueDescription
0sNo animation (default)
2s2 seconds
500ms500 milliseconds
autoFills the entire timeline (for time-based animations)

Important: If duration is 0s, the animation doesn’t play — even if animation-name is set.


3. animation-timing-function

Controls how the animation progresses through its duration — the speed curve.

.box {
    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

Specifies the wait time before the animation starts.

.box {
    animation-delay: 1s;
}
ValueDescription
0sStart immediately (default)
1sWait 1 second
500msWait 500 milliseconds
NegativeStarts partway through the animation

Negative Delay

A negative delay starts the animation already in progress:

animation-delay: -2s; /* Starts 2 seconds into the animation */

Visual comparison:

animation-delay: 0s;   → [start]──────[end]
animation-delay: 1s;   → ────[start]──────[end]
animation-delay: -2s;  → ──[starts 2s in]──[end]

5. animation-iteration-count

Specifies how many times the animation repeats.

.box {
    animation-iteration-count: 3;
}
ValueDescription
1Plays once (default)
3Plays 3 times
infiniteRepeats forever
0.5Plays half the animation
2.5Plays 2.5 cycles

Non-integer values: 0.5 plays half the animation, 2.5 plays two and a half cycles.


6. animation-direction

Specifies whether the animation plays forward, backward, or alternates.

.box {
    animation-direction: alternate-reverse;
}
ValueDescriptionCycle 1Cycle 2Cycle 3
normalForward each cycle
reverseBackward each cycle
alternateForward, then backward
alternate-reverseBackward, then forward

Visual comparison:

normal:             [1→2→3] [1→2→3] [1→2→3]
reverse:            [3→2→1] [3→2→1] [3→2→1]
alternate:          [1→2→3] [3→2→1] [1→2→3]
alternate-reverse:  [3→2→1] [1→2→3] [3→2→1]

Complete Example

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Animation Properties — Part 1</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;
        }

        /* ====== MAIN DEMO BOX ====== */
        .box {
            width: 100px;
            height: 100px;
            background: linear-gradient(135deg, #007bff, #6c5ce7);
            border-radius: 12px;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
            animation-name: slideIn;
            animation-duration: 2s;
            animation-delay: 1s;
            animation-iteration-count: 3;
            animation-timing-function: ease-in-out;
            animation-direction: alternate-reverse;
        }

        @keyframes slideIn {
            from { transform: translateX(-100%); }
            to   { transform: translateX(0); }
        }

        /* ====== TIMING FUNCTIONS ====== */
        .timing-box {
            width: 80px;
            height: 80px;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: bold;
            font-size: 0.7rem;
            animation-name: moveRight;
            animation-duration: 2s;
            animation-iteration-count: infinite;
        }

        .timing-ease {
            background: #007bff;
            animation-timing-function: ease;
        }
        .timing-linear {
            background: #28a745;
            animation-timing-function: linear;
        }
        .timing-ease-in {
            background: #dc3545;
            animation-timing-function: ease-in;
        }
        .timing-ease-out {
            background: #ffc107;
            color: #333;
            animation-timing-function: ease-out;
        }
        .timing-ease-in-out {
            background: #6c5ce7;
            animation-timing-function: ease-in-out;
        }

        @keyframes moveRight {
            from { transform: translateX(0); }
            to   { transform: translateX(150px); }
        }

        /* ====== DELAY COMPARISON ====== */
        .delay-box {
            width: 80px;
            height: 80px;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: bold;
            font-size: 0.7rem;
            animation-name: fadeSlide;
            animation-duration: 1s;
            animation-fill-mode: forwards;
            animation-iteration-count: 1;
            opacity: 0;
        }

        .delay-0 {
            background: #007bff;
            animation-delay: 0s;
        }
        .delay-1 {
            background: #28a745;
            animation-delay: 1s;
        }
        .delay-neg {
            background: #dc3545;
            animation-delay: -0.5s;
        }

        @keyframes fadeSlide {
            from { opacity: 0; transform: translateX(-50px); }
            to   { opacity: 1; transform: translateX(0); }
        }

        /* ====== ITERATION COUNT ====== */
        .iteration-box {
            width: 80px;
            height: 80px;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: bold;
            font-size: 0.7rem;
            animation-name: pulseScale;
            animation-duration: 1s;
            animation-timing-function: ease-in-out;
        }

        .iter-1 {
            background: #007bff;
            animation-iteration-count: 1;
        }
        .iter-3 {
            background: #28a745;
            animation-iteration-count: 3;
        }
        .iter-half {
            background: #ffc107;
            color: #333;
            animation-iteration-count: 0.5;
        }
        .iter-infinite {
            background: #dc3545;
            animation-iteration-count: infinite;
        }

        @keyframes pulseScale {
            0%, 100% { transform: scale(1); }
            50%      { transform: scale(1.3); }
        }

        /* ====== DIRECTION COMPARISON ====== */
        .direction-box {
            width: 80px;
            height: 80px;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: bold;
            font-size: 0.7rem;
            animation-name: slideAcross;
            animation-duration: 2s;
            animation-iteration-count: infinite;
            animation-timing-function: ease-in-out;
        }

        .dir-normal {
            background: #007bff;
            animation-direction: normal;
        }
        .dir-reverse {
            background: #28a745;
            animation-direction: reverse;
        }
        .dir-alternate {
            background: #dc3545;
            animation-direction: alternate;
        }
        .dir-alternate-reverse {
            background: #6c5ce7;
            animation-direction: alternate-reverse;
        }

        @keyframes slideAcross {
            from { transform: translateX(0); }
            to   { transform: translateX(150px); }
        }

        /* ====== PRACTICAL: SLIDE IN BANNER ====== */
        .banner-container {
            padding: 20px;
            background: #e9ecef;
            border-radius: 8px;
            overflow: hidden;
            margin: 15px 0;
        }

        .banner {
            background: linear-gradient(135deg, #007bff, #6c5ce7);
            color: white;
            padding: 20px 30px;
            border-radius: 8px;
            font-weight: bold;
            font-size: 1.2rem;
            text-align: center;
            animation-name: bannerSlide;
            animation-duration: 1s;
            animation-delay: 0.5s;
            animation-fill-mode: backwards;
            animation-timing-function: ease-out;
        }

        @keyframes bannerSlide {
            from {
                opacity: 0;
                transform: translateY(-50px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        /* ====== PRACTICAL: STAGGERED LIST ====== */
        .staggered-list {
            list-style: none;
            padding: 0;
            margin: 15px 0;
        }

        .staggered-list li {
            padding: 12px 20px;
            background: white;
            border-radius: 8px;
            margin-bottom: 8px;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
            animation-name: listItemIn;
            animation-duration: 0.5s;
            animation-fill-mode: both;
            animation-timing-function: ease-out;
            opacity: 0;
            transform: translateX(-30px);
        }

        .staggered-list li:nth-child(1) { animation-delay: 0.1s; }
        .staggered-list li:nth-child(2) { animation-delay: 0.2s; }
        .staggered-list li:nth-child(3) { animation-delay: 0.3s; }
        .staggered-list li:nth-child(4) { animation-delay: 0.4s; }
        .staggered-list li:nth-child(5) { animation-delay: 0.5s; }

        @keyframes listItemIn {
            from {
                opacity: 0;
                transform: translateX(-30px);
            }
            to {
                opacity: 1;
                transform: translateX(0);
            }
        }

        /* ====== PRACTICAL: PULSING NOTIFICATION ====== */
        .notification-container {
            position: relative;
            display: inline-block;
            margin: 20px;
        }

        .notification-badge {
            position: absolute;
            top: -8px;
            right: -8px;
            background: #dc3545;
            color: white;
            border-radius: 50%;
            width: 24px;
            height: 24px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 0.75rem;
            font-weight: bold;
            animation-name: pulseRing;
            animation-duration: 1.5s;
            animation-iteration-count: infinite;
            animation-timing-function: ease-out;
        }

        @keyframes pulseRing {
            0% {
                box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.7);
            }
            70% {
                box-shadow: 0 0 0 12px rgba(220, 53, 69, 0);
            }
            100% {
                box-shadow: 0 0 0 0 rgba(220, 53, 69, 0);
            }
        }

        .notification-icon {
            font-size: 2.5rem;
        }

        /* ====== 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>Animation Properties — Part 1</h1>

    <!-- ====== 1. MAIN DEMO ====== -->
    <section>
        <h2>1. Complete Animation with All Properties</h2>
        <p>This box uses <code>animation-name</code>, <code>animation-duration</code>, <code>animation-delay</code>, <code>animation-iteration-count</code>, <code>animation-timing-function</code>, and <code>animation-direction</code>.</p>

        <div class="demo-area">
            <div class="box"></div>
        </div>

        <div class="code-block">
            @keyframes slideIn {
                from { transform: translateX(-100%); }
                to   { transform: translateX(0); }
            }

            .box {
                animation-name: slideIn;
                animation-duration: 2s;
                animation-delay: 1s;
                animation-iteration-count: 3;
                animation-timing-function: ease-in-out;
                animation-direction: alternate-reverse;
            }
        </div>

        <p class="note">The box waits 1 second, then slides in and out 3 times, alternating direction.</p>
    </section>

    <!-- ====== 2. ANIMATION-NAME ====== -->
    <section>
        <h2>2. animation-name</h2>
        <p>Specifies which <code>@keyframes</code> rule to use. You can specify multiple animations separated by commas.</p>

        <div class="code-block">
            /* Single animation */
            .box {
                animation-name: slideIn;
            }

            /* Multiple animations */
            .box {
                animation-name: slideIn, fadeIn;
                animation-duration: 2s, 1s;
            }
        </div>
    </section>

    <!-- ====== 3. ANIMATION-DURATION ====== -->
    <section>
        <h2>3. animation-duration</h2>
        <p>Specifies how long one cycle takes. <code>0s</code> means no animation.</p>

        <div class="code-block">
            .box { animation-duration: 2s; }   /* 2 seconds */
            .box { animation-duration: 500ms; } /* 500 milliseconds */
            .box { animation-duration: 0s; }   /* No animation */
        </div>

        <p class="note"><strong>Important:</strong> If <code>animation-duration</code> is <code>0s</code> (the default), the animation won't play — even if <code>animation-name</code> is set.</p>
    </section>

    <!-- ====== 4. ANIMATION-TIMING-FUNCTION ====== -->
    <section>
        <h2>4. animation-timing-function</h2>
        <p>Each box moves across the screen with a different timing function.</p>

        <div class="demo-area" style="flex-direction: column; gap: 15px; align-items: flex-start;">
            <div style="display: flex; align-items: center; gap: 15px;">
                <span style="font-weight: bold; min-width: 110px;">ease:</span>
                <div class="timing-box timing-ease">ease</div>
            </div>
            <div style="display: flex; align-items: center; gap: 15px;">
                <span style="font-weight: bold; min-width: 110px;">linear:</span>
                <div class="timing-box timing-linear">linear</div>
            </div>
            <div style="display: flex; align-items: center; gap: 15px;">
                <span style="font-weight: bold; min-width: 110px;">ease-in:</span>
                <div class="timing-box timing-ease-in">ease-in</div>
            </div>
            <div style="display: flex; align-items: center; gap: 15px;">
                <span style="font-weight: bold; min-width: 110px;">ease-out:</span>
                <div class="timing-box timing-ease-out">ease-out</div>
            </div>
            <div style="display: flex; align-items: center; gap: 15px;">
                <span style="font-weight: bold; min-width: 110px;">ease-in-out:</span>
                <div class="timing-box timing-ease-in-out">ease-in-out</div>
            </div>
        </div>

        <div class="code-block">
            @keyframes moveRight {
                from { transform: translateX(0); }
                to   { transform: translateX(150px); }
            }

            .timing-ease        { animation-timing-function: ease; }
            .timing-linear      { animation-timing-function: linear; }
            .timing-ease-in     { animation-timing-function: ease-in; }
            .timing-ease-out    { animation-timing-function: ease-out; }
            .timing-ease-in-out { animation-timing-function: ease-in-out; }
        </div>
    </section>

    <!-- ====== 5. ANIMATION-DELAY ====== -->
    <section>
        <h2>5. animation-delay</h2>
        <p>Compare positive and negative delays. Refresh the page to see the difference.</p>

        <div class="demo-area">
            <div style="text-align: center;">
                <div class="delay-box delay-0">0s</div>
                <p class="note">delay: 0s</p>
            </div>
            <div style="text-align: center;">
                <div class="delay-box delay-1">1s</div>
                <p class="note">delay: 1s</p>
            </div>
            <div style="text-align: center;">
                <div class="delay-box delay-neg">-0.5s</div>
                <p class="note">delay: -0.5s</p>
            </div>
        </div>

        <div class="code-block">
            .delay-0   { animation-delay: 0s; }
            .delay-1   { animation-delay: 1s; }
            .delay-neg { animation-delay: -0.5s; }

            @keyframes fadeSlide {
                from { opacity: 0; transform: translateX(-50px); }
                to   { opacity: 1; transform: translateX(0); }
            }
        </div>

        <p class="note">A <strong>negative delay</strong> starts the animation already partway through. With <code>-0.5s</code> on a <code>1s</code> animation, it starts halfway (at 50% opacity and position).</p>
    </section>

    <!-- ====== 6. ANIMATION-ITERATION-COUNT ====== -->
    <section>
        <h2>6. animation-iteration-count</h2>
        <p>Compare different iteration counts. Watch closely — they all use the same animation.</p>

        <div class="demo-area">
            <div style="text-align: center;">
                <div class="iteration-box iter-1">1×</div>
                <p class="note">count: 1</p>
            </div>
            <div style="text-align: center;">
                <div class="iteration-box iter-3">3×</div>
                <p class="note">count: 3</p>
            </div>
            <div style="text-align: center;">
                <div class="iteration-box iter-half">0.5×</div>
                <p class="note">count: 0.5</p>
            </div>
            <div style="text-align: center;">
                <div class="iteration-box iter-infinite">∞</div>
                <p class="note">count: infinite</p>
            </div>
        </div>

        <div class="code-block">
            .iter-1        { animation-iteration-count: 1; }
            .iter-3        { animation-iteration-count: 3; }
            .iter-half     { animation-iteration-count: 0.5; }
            .iter-infinite { animation-iteration-count: infinite; }

            @keyframes pulseScale {
                0%, 100% { transform: scale(1); }
                50%      { transform: scale(1.3); }
            }
        </div>
    </section>

    <!-- ====== 7. ANIMATION-DIRECTION ====== -->
    <section>
        <h2>7. animation-direction</h2>
        <p>Compare the four direction values. Watch how each box moves.</p>

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

        <div class="code-block">
            @keyframes slideAcross {
                from { transform: translateX(0); }
                to   { transform: translateX(150px); }
            }

            .dir-normal           { animation-direction: normal; }
            .dir-reverse          { animation-direction: reverse; }
            .dir-alternate        { animation-direction: alternate; }
            .dir-alternate-reverse { animation-direction: alternate-reverse; }
        </div>

        <table class="reference-table">
            <tr>
                <th>Value</th>
                <th>Cycle 1</th>
                <th>Cycle 2</th>
                <th>Cycle 3</th>
            </tr>
            <tr>
                <td><code>normal</code></td>
                <td>→</td>
                <td>→</td>
                <td>→</td>
            </tr>
            <tr>
                <td><code>reverse</code></td>
                <td>←</td>
                <td>←</td>
                <td>←</td>
            </tr>
            <tr>
                <td><code>alternate</code></td>
                <td>→</td>
                <td>←</td>
                <td>→</td>
            </tr>
            <tr>
                <td><code>alternate-reverse</code></td>
                <td>←</td>
                <td>→</td>
                <td>←</td>
            </tr>
        </table>
    </section>

    <!-- ====== 8. PRACTICAL: SLIDE-IN BANNER ====== -->
    <section>
        <h2>8. Practical Example: Slide-In Banner</h2>
        <p>Refresh the page to see the banner slide in from the top.</p>

        <div class="banner-container">
            <div class="banner">
                🎉 Welcome! This banner slides in from the top.
            </div>
        </div>

        <div class="code-block">
            .banner {
                animation-name: bannerSlide;
                animation-duration: 1s;
                animation-delay: 0.5s;
                animation-fill-mode: backwards;
                animation-timing-function: ease-out;
            }

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

        <p class="note">The <code>animation-fill-mode: backwards</code> applies the <code>from</code> styles during the delay, so the banner is invisible before it starts.</p>
    </section>

    <!-- ====== 9. PRACTICAL: STAGGERED LIST ====== -->
    <section>
        <h2>9. Practical Example: Staggered List</h2>
        <p>Refresh the page to see the list items appear one by one.</p>

        <ul class="staggered-list">
            <li>✨ First item slides in</li>
            <li>🚀 Second item follows</li>
            <li>🎯 Third item appears</li>
            <li>💎 Fourth item arrives</li>
            <li>🔥 Fifth item completes the list</li>
        </ul>

        <div class="code-block">
            .staggered-list li {
                animation-name: listItemIn;
                animation-duration: 0.5s;
                animation-fill-mode: both;
                animation-timing-function: ease-out;
            }

            .staggered-list li:nth-child(1) { animation-delay: 0.1s; }
            .staggered-list li:nth-child(2) { animation-delay: 0.2s; }
            .staggered-list li:nth-child(3) { animation-delay: 0.3s; }
            .staggered-list li:nth-child(4) { animation-delay: 0.4s; }
            .staggered-list li:nth-child(5) { animation-delay: 0.5s; }

            @keyframes listItemIn {
                from { opacity: 0; transform: translateX(-30px); }
                to   { opacity: 1; transform: translateX(0); }
            }
        </div>
    </section>

    <!-- ====== 10. PRACTICAL: PULSING NOTIFICATION ====== -->
    <section>
        <h2>10. Practical Example: Pulsing Notification</h2>
        <p>A notification badge that pulses to draw attention.</p>

        <div style="text-align: center;">
            <div class="notification-container">
                <span class="notification-icon">🔔</span>
                <span class="notification-badge">3</span>
            </div>
        </div>

        <div class="code-block">
            .notification-badge {
                animation-name: pulseRing;
                animation-duration: 1.5s;
                animation-iteration-count: infinite;
                animation-timing-function: ease-out;
            }

            @keyframes pulseRing {
                0%   { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.7); }
                70%  { box-shadow: 0 0 0 12px rgba(220, 53, 69, 0); }
                100% { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0); }
            }
        </div>
    </section>

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

        <h3>Animation Properties — Part 1</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>
        </table>

        <h3>animation-timing-function Values</h3>
        <table class="reference-table">
            <tr>
                <th>Value</th>
                <th>Description</th>
            </tr>
            <tr>
                <td><code>ease</code></td>
                <td>Slow start, fast middle, slow end (default)</td>
            </tr>
            <tr>
                <td><code>linear</code></td>
                <td>Constant speed</td>
            </tr>
            <tr>
                <td><code>ease-in</code></td>
                <td>Slow start, fast end</td>
            </tr>
            <tr>
                <td><code>ease-out</code></td>
                <td>Fast start, slow end</td>
            </tr>
            <tr>
                <td><code>ease-in-out</code></td>
                <td>Slow start, fast middle, slow end</td>
            </tr>
            <tr>
                <td><code>cubic-bezier(n,n,n,n)</code></td>
                <td>Custom curve</td>
            </tr>
            <tr>
                <td><code>steps(n)</code></td>
                <td>Stepped animation</td>
            </tr>
        </table>

        <h3>animation-iteration-count Values</h3>
        <table class="reference-table">
            <tr>
                <th>Value</th>
                <th>Description</th>
            </tr>
            <tr>
                <td><code>1</code></td>
                <td>Plays once (default)</td>
            </tr>
            <tr>
                <td><code>3</code></td>
                <td>Plays 3 times</td>
            </tr>
            <tr>
                <td><code>infinite</code></td>
                <td>Repeats forever</td>
            </tr>
            <tr>
                <td><code>0.5</code></td>
                <td>Plays half the animation</td>
            </tr>
            <tr>
                <td><code>2.5</code></td>
                <td>Plays 2.5 cycles</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>
    </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>Always specify <code>animation-duration</code> — the default is <code>0s</code></li>
                <li>Use <code>animation-delay</code> for staggered effects</li>
                <li>Use <code>animation-iteration-count: infinite</code> for continuous animations</li>
                <li>Use <code>animation-direction: alternate</code> for back-and-forth motion</li>
                <li>Use negative delays to start animations partway through</li>
                <li>Use <code>transform</code> and <code>opacity</code> for smooth performance</li>
                <li>Respect <code>prefers-reduced-motion</code> for accessibility</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 forget <code>animation-duration</code> — nothing will happen</li>
                <li>Don't use <code>infinite</code> for animations that should stop</li>
                <li>Don't confuse <code>animation-delay</code> with <code>animation-duration</code></li>
                <li>Don't use negative delays without understanding the effect</li>
                <li>Don't animate layout properties like <code>width</code> or <code>height</code></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) {
                .box,
                .banner,
                .staggered-list li,
                .notification-badge {
                    animation: none;
                }
            }

            /* Staggered animation */
            .item:nth-child(1) { animation-delay: 0.1s; }
            .item:nth-child(2) { animation-delay: 0.2s; }
            .item:nth-child(3) { animation-delay: 0.3s; }
        </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-timing-function Values

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

animation-iteration-count Values

ValueDescription
1Plays once (default)
3Plays 3 times
infiniteRepeats forever
0.5Plays half the animation
2.5Plays 2.5 cycles

animation-direction Values

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

Best Practices

Do This:

/* Complete animation setup */
.box {
    animation-name: slideIn;
    animation-duration: 2s;
    animation-timing-function: ease-in-out;
    animation-delay: 0.5s;
    animation-iteration-count: 3;
    animation-direction: alternate;
}

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

/* Continuous animation */
.spinner {
    animation: spin 1s linear infinite;
}

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
    .box {
        animation: none;
    }
}

Don’t Do This:

/* Don't forget animation-duration */
.box {
    animation-name: slideIn; /* Duration is 0s — nothing happens! */
}

/* Don't confuse delay with duration */
.box {
    animation-delay: 2s;    /* Waits 2s before starting */
    animation-duration: 1s; /* Then takes 1s to complete */
}

/* Don't use infinite for one-time animations */
.alert {
    animation: pulse 1s infinite; /* Will pulse forever! */
}

/* Don't forget reduced motion */
@media (prefers-reduced-motion: reduce) {
    /* Missing — animations still play */
}

Pro Tip: The six properties in this lesson are the core of CSS animations. Remember: animation-duration is required (default 0s means no animation). Use animation-delay for staggered effects — applying incremental delays to list items creates a beautiful cascade. animation-iteration-count: infinite is perfect for continuous animations like spinners and pulses. animation-direction: alternate creates natural back-and-forth motion. And always respect prefers-reduced-motion — some users 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!