CSS Animation
Learn how CSS animations create multi-step, repeating, automatic, and controlled motion using @keyframes and animation properties.
Introduction
In the previous lesson, you learned CSS Transition and how property values can change smoothly from one state to another.
Transitions are excellent for simple state changes such as hover effects, focus states, and class changes.
However, some visual effects require multiple steps, automatic playback, repetition, direction control, pausing, and more complex motion sequences.
CSS Animation provides these capabilities using the @keyframes rule and animation properties.
Unlike transitions, CSS animations do not always require a state change such as :hover. They can begin automatically when an element appears.
What is CSS Animation?
CSS Animation is a feature that allows an element to change through one or more visual states over time.
The animation sequence is defined using @keyframes, while animation properties control how the sequence runs.
@keyframes move {
from {
transform: translateX(0);
}
to {
transform: translateX(200px);
}
}
.box {
animation:
move 2s ease;
}Start State
│
▼
Intermediate Frames
│
▼
Final State
0% ───────── 25% ───────── 50% ───────── 75% ───────── 100%Why Do We Need Animations?
Animations are useful when an interface needs motion that is more complex than a simple change between two states.
Multi-Step Motion
Create sequences with several intermediate states.
Repetition
Repeat animations a specific number of times or forever.
Automatic Playback
Start animations without requiring hover or another state change.
Direction Control
Play animations forward, backward, or alternate directions.
Play and Pause
Pause and resume animations when required.
Visual Feedback
Draw attention to loading, notifications, success states, and updates.
Real-World Analogy
Imagine creating a flipbook animation.
Each important drawing represents a key moment. When the pages are shown quickly, the drawings appear to move.
| Flipbook Concept | CSS Animation |
|---|---|
| Animation sequence | @keyframes |
| Important drawings | Keyframes |
| First drawing | 0% or from |
| Last drawing | 100% or to |
| Playback speed | animation-duration |
| Number of repeats | animation-iteration-count |
| Playback direction | animation-direction |
Frame 1 Frame 2 Frame 3 Frame 4
● ● ● ●
│ ╱ ─ ╲
╱ ╲ ╱ ╲ ╱ ╲ ╱ ╲
Rapid Playback Creates Motion
CSS
0% ───────► 33% ───────► 66% ───────► 100%Transition vs Animation
CSS Transition
- Usually needs a property state change.
- Commonly moves between two states.
- Ideal for hover and focus effects.
- Simple to configure.
- Automatically reverses when state changes back.
CSS Animation
- Can start automatically.
- Can contain many keyframes.
- Can repeat automatically.
- Can control direction and fill mode.
- Ideal for complex motion sequences.
| Feature | Transition | Animation |
|---|---|---|
| Needs state change | Usually | No |
| Multiple steps | Limited | Yes |
| Automatic start | Not normally | Yes |
| Repeat | No built-in repetition | Yes |
| Direction control | Limited | Yes |
| Pause and resume | Limited | Yes |
| Uses @keyframes | No | Yes |
How CSS Animation Works
A CSS animation requires keyframes and an element that references those keyframes using animation-name or the animation shorthand.
@keyframes grow {
from {
transform: scale(1);
}
to {
transform: scale(1.3);
}
}
.box {
animation-name: grow;
animation-duration: 1s;
}The @keyframes rule describes what changes. Animation properties describe how the sequence should run.
The @keyframes Rule
The @keyframes rule defines the visual states of an animation.
@keyframes animationName {
from {
/* Starting styles */
}
to {
/* Ending styles */
}
}@keyframes animationName {
0% {
/* Starting styles */
}
50% {
/* Middle styles */
}
100% {
/* Ending styles */
}
}Basic Animation Syntax
.element {
animation-name: move;
animation-duration: 2s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: none;
animation-play-state: running;
}.element {
animation:
move
2s
ease
0s
1
normal
none
running;
}Example 1: Moving Box
<div class="moving-box">
Move
</div>@keyframes moveBox {
from {
transform:
translateX(0);
}
to {
transform:
translateX(250px);
}
}
.moving-box {
width: 80px;
height: 80px;
display: grid;
place-items: center;
background: #6c5ce7;
color: white;
border-radius: 12px;
animation-name:
moveBox;
animation-duration:
2s;
}from and to Keywords
The from keyword represents the beginning of an animation, while to represents the end.
| Keyword | Equivalent Percentage |
|---|---|
| from | 0% |
| to | 100% |
@keyframes fadeOne {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeTwo {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}Percentage Keyframes
Percentage keyframes allow an animation to contain many important states.
@keyframes change {
0% {
transform:
translateX(0);
background:
#6c5ce7;
}
25% {
transform:
translateX(100px);
background:
#0984e3;
}
50% {
transform:
translateX(200px);
background:
#00b894;
}
75% {
transform:
translateX(100px);
background:
#fdcb6e;
}
100% {
transform:
translateX(0);
background:
#6c5ce7;
}
}The percentage does not represent seconds. It represents a position within the total animation duration.
Example 2: Multi-Step Animation
<div class="multi-box"></div>@keyframes travel {
0% {
transform:
translate(0, 0);
}
25% {
transform:
translate(220px, 0);
}
50% {
transform:
translate(220px, 100px);
}
75% {
transform:
translate(0, 100px);
}
100% {
transform:
translate(0, 0);
}
}
.multi-box {
width: 60px;
height: 60px;
background: #6c5ce7;
border-radius: 12px;
animation:
travel 4s ease infinite;
}Animation Properties
| Property | Purpose |
|---|---|
| animation-name | Selects the @keyframes animation |
| animation-duration | Defines how long one cycle takes |
| animation-timing-function | Controls the speed curve |
| animation-delay | Defines waiting time before starting |
| animation-iteration-count | Defines number of repetitions |
| animation-direction | Controls playback direction |
| animation-fill-mode | Controls styles before and after animation |
| animation-play-state | Runs or pauses the animation |
| animation | Shorthand for animation properties |
animation-name
The animation-name property connects an element to a named @keyframes rule.
@keyframes rotateBox {
to {
transform:
rotate(360deg);
}
}
.box {
animation-name:
rotateBox;
}If animation-name does not match an existing @keyframes name, the animation will not run.
animation-duration
The animation-duration property defines how long one complete animation cycle takes.
.fast {
animation-duration: 0.5s;
}
.medium {
animation-duration: 2s;
}
.slow {
animation-duration: 5s;
}An animation will not visibly run unless a duration greater than zero is provided.
Time Units
| Unit | Meaning | Example |
|---|---|---|
| s | Seconds | 2s |
| ms | Milliseconds | 500ms |
.one {
animation-duration: 1s;
}
.two {
animation-duration: 1000ms;
}Example 3: Different Durations
<div class="duration-box fast">
Fast
</div>
<div class="duration-box medium">
Medium
</div>
<div class="duration-box slow">
Slow
</div>@keyframes slide {
from {
transform:
translateX(0);
}
to {
transform:
translateX(250px);
}
}
.duration-box {
width: 90px;
padding: 14px;
margin-bottom: 12px;
background: #6c5ce7;
color: white;
text-align: center;
border-radius: 8px;
animation-name:
slide;
animation-iteration-count:
infinite;
animation-direction:
alternate;
}
.fast {
animation-duration: 0.8s;
}
.medium {
animation-duration: 2s;
}
.slow {
animation-duration: 4s;
}animation-timing-function
The animation-timing-function property controls how animation speed changes between keyframes.
.box {
animation-timing-function:
ease-in-out;
}Timing Function Values
| Value | Behavior |
|---|---|
| ease | Slow start, faster middle, slow end |
| linear | Constant speed |
| ease-in | Slow start |
| ease-out | Slow end |
| ease-in-out | Slow start and slow end |
| cubic-bezier() | Custom speed curve |
| steps() | Movement in fixed jumps |
When an animation contains several keyframes, the timing function controls movement between the keyframe states.
Example 4: Timing Functions
@keyframes race {
from {
transform:
translateX(0);
}
to {
transform:
translateX(280px);
}
}
.ease {
animation:
race 3s ease infinite alternate;
}
.linear {
animation:
race 3s linear infinite alternate;
}
.ease-in {
animation:
race 3s ease-in infinite alternate;
}
.ease-out {
animation:
race 3s ease-out infinite alternate;
}animation-delay
The animation-delay property defines how long the browser waits before an animation starts.
.box {
animation-name: move;
animation-duration: 2s;
animation-delay: 1s;
}Positive Delay
A positive animation delay waits before the animation begins.
.box {
animation:
move 2s ease 1s;
}Negative Delay
A negative animation delay starts the animation immediately as if part of the animation had already completed.
.box {
animation:
move 4s linear -2s;
}Negative delays are useful when several repeating elements should appear at different positions in the same animation cycle.
Example 5: Delayed Animation
@keyframes appear {
from {
opacity: 0;
transform:
translateY(30px);
}
to {
opacity: 1;
transform:
translateY(0);
}
}
.delay-card {
animation:
appear
0.8s
ease
1.5s
forwards;
}animation-iteration-count
The animation-iteration-count property defines how many times an animation should repeat.
.box {
animation-iteration-count: 3;
}| Value | Meaning |
|---|---|
| 1 | Runs once |
| 2 | Runs twice |
| 3 | Runs three times |
| 0.5 | Runs half of one cycle |
| infinite | Repeats forever |
Infinite Animation
The infinite keyword makes an animation repeat continuously.
.spinner {
animation:
rotate 1s linear infinite;
}Continuous animation can distract users and consume resources. Use it only when the repeated motion serves a clear purpose.
Example 6: Repeating Animation
@keyframes blink {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.2;
}
}
.status-dot {
width: 18px;
height: 18px;
background: #00b894;
border-radius: 50%;
animation:
blink
1.2s
ease-in-out
infinite;
}animation-direction
The animation-direction property controls the direction in which animation cycles play.
| Value | Behavior |
|---|---|
| normal | Every cycle plays from start to end |
| reverse | Every cycle plays from end to start |
| alternate | Odd cycles forward, even cycles backward |
| alternate-reverse | Odd cycles backward, even cycles forward |
normal
Cycle 1: 0% ─────────► 100%
Cycle 2: 0% ─────────► 100%reverse
Cycle 1: 100% ─────────► 0%
Cycle 2: 100% ─────────► 0%alternate
Cycle 1: 0% ─────────► 100%
Cycle 2: 100% ─────────► 0%
Cycle 3: 0% ─────────► 100%alternate-reverse
Cycle 1: 100% ─────────► 0%
Cycle 2: 0% ─────────► 100%
Cycle 3: 100% ─────────► 0%Example 7: Animation Directions
.normal {
animation-direction: normal;
}
.reverse {
animation-direction: reverse;
}
.alternate {
animation-direction: alternate;
}
.alternate-reverse {
animation-direction:
alternate-reverse;
}animation-fill-mode
The animation-fill-mode property controls which keyframe styles apply before an animation starts and after it finishes.
| Value | Behavior |
|---|---|
| none | No keyframe styles retained outside animation |
| forwards | Keeps final keyframe styles after animation |
| backwards | Applies starting keyframe styles during delay |
| both | Combines forwards and backwards behavior |
none
The none value is the default. The element returns to its normal CSS styles after the animation ends.
forwards
The forwards value keeps the styles from the animation final keyframe after the animation finishes.
.box {
animation:
move 2s ease forwards;
}backwards
The backwards value applies the starting keyframe styles during the animation delay.
both
The both value applies the behavior of both forwards and backwards.
Example 8: Fill Modes
@keyframes reveal {
from {
opacity: 0;
transform:
translateY(30px);
}
to {
opacity: 1;
transform:
translateY(0);
}
}
.card {
animation:
reveal
1s
ease
1s
both;
}The both value can apply the starting state during a delay and preserve the ending state after the animation completes.
animation-play-state
The animation-play-state property controls whether an animation is running or paused.
| Value | Meaning |
|---|---|
| running | Animation plays normally |
| paused | Animation stops at its current position |
Pause on Hover
.box {
animation:
rotate 3s linear infinite;
}
.box:hover {
animation-play-state:
paused;
}Example 9: Play and Pause
@keyframes orbit {
to {
transform:
rotate(360deg);
}
}
.orbit {
animation:
orbit 3s linear infinite;
}
.orbit:hover {
animation-play-state:
paused;
}Animation Shorthand
The animation shorthand combines several animation properties into one declaration.
.element {
animation:
name
duration
timing-function
delay
iteration-count
direction
fill-mode
play-state;
}Shorthand Order
.box {
animation:
move
2s
ease-in-out
0.5s
infinite
alternate
both
running;
}| Value | Meaning |
|---|---|
| move | Animation name |
| 2s | Duration |
| ease-in-out | Timing function |
| 0.5s | Delay |
| infinite | Iteration count |
| alternate | Direction |
| both | Fill mode |
| running | Play state |
When two time values appear in animation shorthand, the first is duration and the second is delay.
Example 10: Shorthand Animation
@keyframes float {
from {
transform:
translateY(0);
}
to {
transform:
translateY(-25px);
}
}
.float-card {
animation:
float
1.5s
ease-in-out
0s
infinite
alternate;
}Multiple Animations
An element can run several animations at the same time by separating animation definitions with commas.
.box {
animation:
move 3s ease infinite alternate,
rotate 2s linear infinite,
colorChange 4s ease infinite;
}Example 11: Multiple Animations
@keyframes move {
from {
transform:
translateX(0)
rotate(0);
}
to {
transform:
translateX(220px)
rotate(360deg);
}
}
@keyframes changeColor {
0% {
background:
#6c5ce7;
}
50% {
background:
#00b894;
}
100% {
background:
#e17055;
}
}
.multi-animation {
animation:
move
3s
ease-in-out
infinite
alternate,
changeColor
4s
linear
infinite;
}Transform Animations
The transform property is commonly animated for movement, rotation, scaling, and skewing.
@keyframes transformExample {
0% {
transform:
translateX(0)
rotate(0)
scale(1);
}
100% {
transform:
translateX(200px)
rotate(360deg)
scale(1.2);
}
}Animating transform often avoids repeated layout calculations and is widely used for smooth visual movement.
Example 12: Loading Spinner
<div class="spinner"></div>@keyframes spin {
to {
transform:
rotate(360deg);
}
}
.spinner {
width: 60px;
height: 60px;
border:
7px solid #dfe6e9;
border-top-color:
#6c5ce7;
border-radius: 50%;
animation:
spin
0.8s
linear
infinite;
}Opacity Animations
Animating opacity creates fade-in, fade-out, blinking, and reveal effects.
@keyframes fade {
from {
opacity: 0;
}
to {
opacity: 1;
}
}Example 13: Fade In
@keyframes fadeIn {
from {
opacity: 0;
transform:
translateY(20px);
}
to {
opacity: 1;
transform:
translateY(0);
}
}
.fade-card {
animation:
fadeIn
0.8s
ease
both;
}Bouncing Animation
A bouncing effect can be created by changing vertical translation at several keyframes.
@keyframes bounce {
0%,
100% {
transform:
translateY(0);
}
50% {
transform:
translateY(-80px);
}
}Example 14: Bouncing Ball
@keyframes bounceBall {
0%,
100% {
transform:
translateY(0)
scaleX(1.1)
scaleY(0.9);
}
50% {
transform:
translateY(-100px)
scaleX(0.95)
scaleY(1.05);
}
}
.ball {
width: 70px;
height: 70px;
background:
#6c5ce7;
border-radius: 50%;
animation:
bounceBall
1s
ease-in-out
infinite;
}Pulse Animation
A pulse animation repeatedly changes scale, opacity, or shadow to attract attention.
Example 15: Notification Pulse
@keyframes pulse {
0% {
transform:
scale(1);
box-shadow:
0 0 0 0
rgba(225, 112, 85, 0.5);
}
70% {
transform:
scale(1.08);
box-shadow:
0 0 0 18px
rgba(225, 112, 85, 0);
}
100% {
transform:
scale(1);
box-shadow:
0 0 0 0
rgba(225, 112, 85, 0);
}
}
.notification {
animation:
pulse
1.5s
ease
infinite;
}Typing Animation
A typing effect can be created by animating width in discrete steps while hiding overflowing text.
Example 16: Typing Effect
<h2 class="typing">
Learn CSS Animation
</h2>@keyframes typing {
from {
width: 0;
}
to {
width: 20ch;
}
}
@keyframes cursor {
50% {
border-color:
transparent;
}
}
.typing {
width: 20ch;
overflow: hidden;
white-space: nowrap;
border-right:
3px solid #6c5ce7;
animation:
typing
3s
steps(20)
forwards,
cursor
0.7s
step-end
infinite;
}Animation Events
JavaScript can listen for events generated by CSS animations.
| Event | When It Occurs |
|---|---|
| animationstart | Animation begins |
| animationiteration | A new animation cycle begins |
| animationend | Animation finishes |
| animationcancel | Animation is cancelled |
const box =
document.querySelector('.box');
box.addEventListener(
'animationend',
() => {
console.log(
'Animation completed'
);
}
);Controlling Animation with JavaScript
JavaScript can start, stop, pause, resume, or replace animations by changing classes and styles.
const box =
document.querySelector('.box');
const button =
document.querySelector('.button');
button.addEventListener(
'click',
() => {
box.classList.toggle(
'animate'
);
}
);.box.animate {
animation:
bounce
1s
ease
infinite;
}Animation Performance
Animations can affect browser performance differently depending on which properties change and how many elements are animated.
Commonly Better for Motion
- transform
- opacity
- Often avoids repeated layout calculations.
- Suitable for frequent visual updates.
Can Require More Work
- width
- height
- margin
- top and left in complex layouts
A smooth animation is not only about code. Avoid animating too many large elements at the same time.
prefers-reduced-motion
Some users prefer reduced motion. CSS can detect this preference and reduce or remove non-essential animations.
.card {
animation:
float 2s ease infinite alternate;
}
@media (
prefers-reduced-motion:
reduce
) {
.card {
animation: none;
}
}Important information and controls should remain understandable and usable when animations are disabled.
Complete Animation Example
The following example combines entrance animations, floating motion, rotation, pulsing, staggered delays, multiple keyframes, and interactive animation states.
<section class="animation-showcase">
<div class="showcase-content">
<span class="showcase-badge">
CSS Animation
</span>
<h2>
Bring Interfaces to Life
</h2>
<p>
Create smooth, meaningful,
and engaging motion with CSS.
</p>
<button class="showcase-button">
Start Learning
<span>→</span>
</button>
</div>
<div class="showcase-visual">
<div class="orbit-ring ring-one">
<span></span>
</div>
<div class="orbit-ring ring-two">
<span></span>
</div>
<div class="center-icon">
✨
</div>
<div class="floating-card card-one">
@keyframes
</div>
<div class="floating-card card-two">
transform
</div>
<div class="floating-card card-three">
animation
</div>
</div>
</section>@keyframes fadeUp {
from {
opacity: 0;
transform:
translateY(30px);
}
to {
opacity: 1;
transform:
translateY(0);
}
}
@keyframes orbit {
to {
transform:
rotate(360deg);
}
}
@keyframes reverseOrbit {
to {
transform:
rotate(-360deg);
}
}
@keyframes pulseCenter {
0%,
100% {
transform:
scale(1);
box-shadow:
0 0 0 0
rgba(108, 92, 231, 0.35);
}
50% {
transform:
scale(1.08);
box-shadow:
0 0 0 20px
rgba(108, 92, 231, 0);
}
}
@keyframes floatCard {
from {
transform:
translateY(0);
}
to {
transform:
translateY(-18px);
}
}
.animation-showcase {
display: grid;
grid-template-columns:
repeat(
2,
minmax(0, 1fr)
);
gap: 50px;
align-items: center;
min-height: 500px;
padding: 50px;
overflow: hidden;
background:
linear-gradient(
135deg,
#f5f6fa,
#eef0ff
);
border-radius: 24px;
}
.showcase-content > * {
opacity: 0;
animation:
fadeUp
0.8s
ease
forwards;
}
.showcase-badge {
display: inline-block;
padding: 8px 16px;
background:
rgba(108, 92, 231, 0.12);
color: #6c5ce7;
border-radius: 999px;
font-weight: 700;
animation-delay:
0.2s;
}
.showcase-content h2 {
margin:
20px 0 14px;
font-size:
clamp(
2rem,
5vw,
3.5rem
);
animation-delay:
0.4s;
}
.showcase-content p {
color: #636e72;
line-height: 1.7;
animation-delay:
0.6s;
}
.showcase-button {
display: inline-flex;
align-items: center;
gap: 10px;
margin-top: 20px;
padding: 14px 24px;
border: none;
background: #6c5ce7;
color: white;
border-radius: 10px;
cursor: pointer;
animation-delay:
0.8s;
}
.showcase-button span {
animation:
arrowMove
0.8s
ease-in-out
infinite
alternate;
}
@keyframes arrowMove {
to {
transform:
translateX(6px);
}
}
.showcase-visual {
position: relative;
min-height: 380px;
display: grid;
place-items: center;
}
.orbit-ring {
position: absolute;
border:
2px dashed
rgba(108, 92, 231, 0.3);
border-radius: 50%;
}
.ring-one {
width: 260px;
height: 260px;
animation:
orbit
8s
linear
infinite;
}
.ring-two {
width: 340px;
height: 340px;
animation:
reverseOrbit
12s
linear
infinite;
}
.orbit-ring span {
position: absolute;
top: -10px;
left: 50%;
width: 20px;
height: 20px;
background: #6c5ce7;
border-radius: 50%;
}
.ring-two span {
background: #00b894;
}
.center-icon {
width: 110px;
height: 110px;
display: grid;
place-items: center;
z-index: 2;
background: #6c5ce7;
color: white;
border-radius: 30px;
font-size: 3rem;
animation:
pulseCenter
2s
ease-in-out
infinite;
}
.floating-card {
position: absolute;
z-index: 3;
padding: 12px 18px;
background: white;
border-radius: 10px;
box-shadow:
0 12px 30px
rgba(0, 0, 0, 0.1);
font-weight: 600;
animation:
floatCard
1.8s
ease-in-out
infinite
alternate;
}
.card-one {
top: 35px;
left: 10px;
}
.card-two {
right: 0;
top: 130px;
animation-delay:
-0.6s;
}
.card-three {
bottom: 30px;
left: 50px;
animation-delay:
-1.2s;
}
@media (
max-width: 800px
) {
.animation-showcase {
grid-template-columns:
1fr;
}
}
@media (
prefers-reduced-motion:
reduce
) {
*,
*::before,
*::after {
animation-duration:
0.01ms !important;
animation-iteration-count:
1 !important;
}
}Browser Rendering Flow
When an animation runs, the browser reads the keyframes, calculates progress, determines intermediate values, and renders the current visual state.
@keyframes
│
▼
Animation Properties
│
▼
Delay
│
▼
Animation Starts
│
▼
Current Time
│
▼
Calculate Progress %
│
▼
Find Keyframe Values
│
▼
Calculate Intermediate State
│
▼
Render Frame
│
▼
More Time Remaining?
│
┌──┴──┐
│ │
Yes No
│ │
▼ ▼
Next Repeat or
Frame FinishReal-World Applications
Loading Indicators
Create spinners, dots, progress effects, and skeleton loaders.
Notifications
Pulse or shake elements to indicate new activity.
Entrance Effects
Fade, slide, or scale content into view.
Attention Effects
Highlight important updates and calls to action.
Illustrations
Animate decorative shapes, icons, and visual scenes.
Data Visualization
Reveal charts, bars, indicators, and changing values.
Text Effects
Create typing, blinking cursor, and reveal animations.
Interactive Interfaces
Animate menus, panels, buttons, cards, and controls.
Advantages
Multi-Step Control
Define many visual states using percentage keyframes.
Automatic Playback
Run animations without requiring user interaction.
Repetition
Repeat animations a fixed number of times or forever.
Direction Control
Play forward, backward, or alternate directions.
Play State
Pause and resume animations.
Fill Modes
Control styles before and after the animation.
Multiple Animations
Run several animation sequences on one element.
JavaScript Integration
Use classes and events to control animation behavior.
Common Beginner Mistakes
An animation name must reference a defined keyframe sequence.
The animation-name value must match the @keyframes name.
The default duration is 0s, so the animation will not visibly run.
Duration and delay values require units such as s or ms.
Keyframe percentages represent progress through the total duration.
Continuous animations can distract users and consume resources.
Duration controls cycle length, while delay controls waiting time.
The first time value is duration and the second is delay.
The element may return to its original styles after the animation finishes.
forwards preserves the final state but does not repeat the animation.
reverse always plays backward, while alternate changes direction each cycle.
Large numbers of simultaneous animations can reduce performance.
Some layout-related properties require more rendering work.
Decorative motion can distract users from important content.
Some users prefer reduced or removed motion.
Essential information should remain available when animations are disabled.
Slow animations can make an interface feel unresponsive.
Very fast movement can be difficult to understand.
Large animations may overflow or perform differently on smaller devices.
Animations can be cancelled, removed, or interrupted.
Best Practices
- Use animations to support meaning and interaction.
- Avoid motion that distracts from important content.
- Use transitions for simple two-state changes.
- Use animations for multi-step or repeating sequences.
- Give every animation a clear purpose.
- Use descriptive @keyframes names.
- Keep animation names consistent.
- Make sure animation-name matches the @keyframes name.
- Always provide a duration greater than zero.
- Use seconds or milliseconds consistently.
- Remember that 1000ms equals 1s.
- Keep common interface animations relatively short.
- Use longer durations only when users need to observe the motion.
- Use percentage keyframes for multi-step sequences.
- Use from and to for simple start-to-end animations.
- Remember that from equals 0%.
- Remember that to equals 100%.
- Remember that percentages represent progress, not seconds.
- Use intermediate keyframes only when they improve the sequence.
- Avoid unnecessary keyframes.
- Choose timing functions intentionally.
- Use ease for general-purpose motion.
- Use linear for constant-speed movement such as rotation.
- Use ease-in for accelerating movement.
- Use ease-out for decelerating movement.
- Use ease-in-out for smooth starts and endings.
- Use cubic-bezier() for carefully designed custom motion.
- Use steps() for discrete frame-like changes.
- Use animation-delay carefully.
- Avoid delaying important feedback.
- Use negative delays when continuous animations need staggered starting positions.
- Use animation-iteration-count to control repetition.
- Avoid infinite animation unless repetition is meaningful.
- Pause or reduce continuous decorative animations when appropriate.
- Use animation-direction to avoid abrupt resets when suitable.
- Use alternate for smooth back-and-forth movement.
- Use reverse only when the sequence should always run backward.
- Use alternate-reverse when the first cycle should begin backward.
- Use animation-fill-mode when keyframe styles should apply outside the active animation.
- Use forwards to preserve the final keyframe state.
- Use backwards to apply the starting state during delay.
- Use both when both behaviors are needed.
- Use animation-play-state for pause and resume behavior.
- Pause animations when users need time to inspect moving content.
- Use animation shorthand for concise declarations.
- Remember that the first shorthand time is duration.
- Remember that the second shorthand time is delay.
- Separate multiple animations with commas.
- Keep multiple animation definitions readable.
- Avoid combining too many animations on one element.
- Use transform for visual movement.
- Use translate() instead of layout changes for simple movement.
- Use rotate() for spinning and orbital effects.
- Use scale() for pulse and emphasis effects.
- Use opacity for fade effects.
- Combine transform and opacity for entrance animations.
- Avoid animating width and height when transform can achieve the visual effect.
- Avoid unnecessary layout-changing animations.
- Test animation performance on lower-powered devices.
- Test animations with many elements on the page.
- Avoid animating very large background areas continuously.
- Use browser developer tools to inspect animations.
- Check whether animation-duration is greater than zero.
- Check whether the keyframe name matches.
- Check whether another CSS rule overrides the animation.
- Check shorthand commas when multiple animations fail.
- Check animation-play-state if an animation appears frozen.
- Check animation-fill-mode when final styles disappear.
- Check animation-direction when movement appears reversed.
- Check animation-iteration-count when repetition is unexpected.
- Use animation events only when JavaScript truly needs them.
- Remember that animationiteration fires for repeated cycles.
- Handle animation cancellation when necessary.
- Use class changes to trigger animations from JavaScript.
- Keep JavaScript responsible for state and CSS responsible for visual motion when practical.
- Avoid manually calculating every animation frame in JavaScript when CSS can handle the effect.
- Use semantic HTML beneath animated interfaces.
- Do not depend on animation alone to communicate important information.
- Use text, icons, labels, or other visual indicators with motion.
- Respect prefers-reduced-motion.
- Reduce or remove non-essential animations when requested.
- Keep functionality available when animation is disabled.
- Avoid rapid flashing effects.
- Avoid excessive shaking or large repeated movement.
- Keep focus indicators visible during animations.
- Do not animate controls away while users are interacting with them.
- Keep clickable targets stable.
- Test hover-triggered animation behavior on touch devices.
- Test animations on narrow screens.
- Prevent animated elements from causing unwanted horizontal scrolling.
- Use overflow carefully around moving elements.
- Avoid clipping focus indicators.
- Create consistent motion patterns across a project.
- Use similar durations for similar types of movement.
- Use consistent easing curves for related components.
- Use faster motion for small interface changes.
- Use slightly longer motion for larger travel distances.
- Use staggered delays carefully.
- Avoid making users wait for decorative sequences to finish.
- Keep loading animations lightweight.
- Stop loading animations when loading completes.
- Use infinite rotation with linear timing for common spinners.
- Use alternate direction for floating effects.
- Use fill-mode both for many entrance animations with delays.
- Use steps() for typing and sprite-like effects.
- Keep animation code organized near the components that use it.
- Reuse keyframes when several elements share the same motion.
- Create separate keyframes when motion behavior is meaningfully different.
- Avoid changing too many unrelated properties inside one animation.
- Choose the simplest animation that solves the visual requirement.
- Keep animations smooth, accessible, performant, and purposeful.
Define the sequence with @keyframes, connect it using animation-name, set the duration, and then control timing, delay, repetition, direction, fill behavior, and play state.
Frequently Asked Questions
What is CSS Animation?
CSS Animation allows elements to change through one or more visual states over time using @keyframes and animation properties.
What is @keyframes?
@keyframes defines the important states of a CSS animation.
What does from mean?
from represents the beginning of the animation and is equivalent to 0%.
What does to mean?
to represents the end of the animation and is equivalent to 100%.
Can an animation have more than two states?
Yes. Percentage keyframes can define any number of intermediate states.
Do keyframe percentages represent seconds?
No. They represent progress through the total animation duration.
What does animation-name do?
It connects an element to a named @keyframes rule.
What does animation-duration do?
It defines how long one complete animation cycle takes.
What is the default animation duration?
The default duration is 0s.
What does animation-timing-function do?
It controls how animation speed changes between keyframes.
What does animation-delay do?
It defines how long the browser waits before starting the animation.
Can animation-delay be negative?
Yes. A negative delay starts the animation immediately from a later point in its timeline.
What does animation-iteration-count do?
It defines how many times an animation repeats.
How do I repeat an animation forever?
Use animation-iteration-count: infinite.
Can iteration count use decimal values?
Yes. A value such as 0.5 runs half of one animation cycle.
What does animation-direction do?
It controls whether animation cycles play forward, backward, or alternate directions.
What is the difference between reverse and alternate?
reverse plays every cycle backward, while alternate changes direction after each cycle.
What does animation-fill-mode do?
It controls which keyframe styles apply before the animation starts and after it ends.
What does forwards do?
forwards preserves the final keyframe styles after the animation finishes.
What does backwards do?
backwards applies the starting keyframe styles during the animation delay.
What does both do?
both combines the behavior of forwards and backwards.
What does animation-play-state do?
It controls whether an animation is running or paused.
Can I pause an animation on hover?
Yes. Set animation-play-state: paused inside the :hover rule.
Can one element have multiple animations?
Yes. Separate multiple animation definitions with commas.
What is the animation shorthand?
It combines animation name, duration, timing function, delay, iteration count, direction, fill mode, and play state.
Which shorthand time value is duration?
The first time value is the animation duration.
Which shorthand time value is delay?
The second time value is the animation delay.
Can CSS animations start automatically?
Yes. They can start automatically when the animation styles are applied.
Can JavaScript control CSS animations?
Yes. JavaScript can add classes, change animation properties, pause animations, and listen for animation events.
What is animationstart?
It is an event that fires when an animation begins.
What is animationiteration?
It is an event that fires when a repeating animation completes a cycle and begins another.
What is animationend?
It is an event that fires when a finite animation finishes.
Which properties are commonly good for animation performance?
transform and opacity are commonly preferred for many visual animation effects.
Should every animation use infinite?
No. Infinite animation should be used only when continuous repetition serves a clear purpose.
What is prefers-reduced-motion?
It is a media feature that allows CSS to reduce or remove motion when the user prefers less animation.
What is the difference between CSS transition and animation?
A transition usually handles a change between states, while an animation can define multiple keyframes, run automatically, repeat, reverse, and pause.
When should I use transition?
Use transitions for simple state changes such as hover, focus, and class changes.
When should I use animation?
Use animations for multi-step sequences, automatic playback, repetition, loaders, entrance effects, and complex motion.
What comes after CSS Animation?
The next lesson covers CSS Media Queries, including responsive design, breakpoints, viewport conditions, mobile-first design, desktop-first design, orientation, media features, and practical responsive layouts.
Key Takeaways
- CSS animations create visual sequences over time.
- @keyframes defines the animation states.
- from is equivalent to 0%.
- to is equivalent to 100%.
- Percentage keyframes create multi-step animations.
- Keyframe percentages represent progress through the total duration.
- animation-name selects the keyframe sequence.
- animation-duration defines one cycle length.
- The default duration is 0s.
- animation-timing-function controls speed changes.
- animation-delay controls when the animation starts.
- Negative delays start partway through the animation.
- animation-iteration-count controls repetition.
- infinite repeats the animation continuously.
- animation-direction controls playback direction.
- normal plays forward.
- reverse plays backward.
- alternate changes direction each cycle.
- alternate-reverse begins backward and alternates.
- animation-fill-mode controls styles outside the active animation.
- forwards keeps the final state.
- backwards applies the starting state during delay.
- both combines forwards and backwards.
- animation-play-state can pause and resume animations.
- Multiple animations are separated with commas.
- The animation shorthand combines animation settings.
- The first shorthand time is duration.
- The second shorthand time is delay.
- Transform and opacity are commonly useful for smooth animation.
- Animation events allow JavaScript to react to animation activity.
- prefers-reduced-motion helps respect user motion preferences.
- Animations should be purposeful, accessible, and performant.
Summary
CSS Animation allows elements to move through one or more visual states over time.
The @keyframes rule defines the important states of an animation.
Simple animations can use from and to, while complex animations can use percentage keyframes.
The animation-name property connects an element to a named keyframe sequence.
The animation-duration property defines how long one complete cycle takes.
The animation-timing-function property controls how speed changes between keyframes.
The animation-delay property controls how long the browser waits before the animation begins.
The animation-iteration-count property defines how many times the animation repeats.
The infinite keyword creates continuously repeating animations.
The animation-direction property controls whether cycles play forward, backward, or alternate directions.
The animation-fill-mode property controls which keyframe styles apply before and after the animation.
The animation-play-state property can run or pause an animation.
The animation shorthand combines the animation name, duration, timing function, delay, iteration count, direction, fill mode, and play state.
Multiple animations can run on one element by separating animation definitions with commas.
Transform and opacity are commonly used for movement, rotation, scaling, fading, loaders, entrance effects, and interactive motion.
JavaScript can control CSS animations using classes, styles, and animation events.
For accessible interfaces, non-essential animations should be reduced or removed when the user prefers reduced motion.
CSS animations are ideal for loaders, notifications, entrance effects, decorative illustrations, typing effects, repeating movement, and complex multi-step visual sequences.
In the next lesson, you will learn CSS Media Queries, including responsive design, breakpoints, viewport widths, mobile-first design, desktop-first design, orientation, media features, and complete responsive layout examples.