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
| Property | Description | Default |
|---|---|---|
animation-name | Name of the @keyframes rule | none |
animation-duration | How long one cycle takes | 0s |
animation-timing-function | Speed curve | ease |
animation-delay | Wait before starting | 0s |
animation-iteration-count | How many times to repeat | 1 |
animation-direction | Direction of each cycle | normal |
1. animation-name
Specifies the name of the @keyframes rule that defines the animation.
.box {
animation-name: slideIn;
}
| Value | Description |
|---|---|
none | No animation (default) |
custom-name | Name of a @keyframes rule |
| Multiple | Comma-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;
}
| Value | Description |
|---|---|
0s | No animation (default) |
2s | 2 seconds |
500ms | 500 milliseconds |
auto | Fills 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;
}
| Value | Description |
|---|---|
ease | Slow start, fast middle, slow end (default) |
linear | Constant speed |
ease-in | Slow start, fast end |
ease-out | Fast start, slow end |
ease-in-out | Slow 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;
}
| Value | Description |
|---|---|
0s | Start immediately (default) |
1s | Wait 1 second |
500ms | Wait 500 milliseconds |
| Negative | Starts 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;
}
| Value | Description |
|---|---|
1 | Plays once (default) |
3 | Plays 3 times |
infinite | Repeats forever |
0.5 | Plays half the animation |
2.5 | Plays 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;
}
| Value | Description | Cycle 1 | Cycle 2 | Cycle 3 |
|---|---|---|---|---|
normal | Forward each cycle | → | → | → |
reverse | Backward each cycle | ← | ← | ← |
alternate | Forward, then backward | → | ← | → |
alternate-reverse | Backward, 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
| Property | Description | Default |
|---|---|---|
animation-name | Name of the @keyframes rule | none |
animation-duration | How long one cycle takes | 0s |
animation-timing-function | Speed curve | ease |
animation-delay | Wait before starting | 0s |
animation-iteration-count | How many times to repeat | 1 |
animation-direction | Direction of each cycle | normal |
animation-timing-function Values
| Value | Description |
|---|---|
ease | Slow start, fast middle, slow end (default) |
linear | Constant speed |
ease-in | Slow start, fast end |
ease-out | Fast start, slow end |
ease-in-out | Slow start, fast middle, slow end |
cubic-bezier(n,n,n,n) | Custom curve |
steps(n) | Stepped animation |
animation-iteration-count Values
| Value | Description |
|---|---|
1 | Plays once (default) |
3 | Plays 3 times |
infinite | Repeats forever |
0.5 | Plays half the animation |
2.5 | Plays 2.5 cycles |
animation-direction Values
| Value | Description |
|---|---|
normal | Forward each cycle (default) |
reverse | Backward each cycle |
alternate | Forward, then backward |
alternate-reverse | Backward, 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!