Transitions and Simple Animations

Welcome back.
In the previous lesson, you learned backgrounds, borders, and shadows.
Your cards became polished.
Your buttons started looking respectable.
CSS finally combed its hair.
Now we add movement.
Not chaos.
Not spinning everything like a website made by an excited squirrel.
Smooth movement.
Today we will learn transitions and simple animations.
Transitions help CSS changes happen smoothly.
Animations let elements move automatically.
Used well, they make a website feel alive.
Used badly, they make users wonder if the page needs medical attention.
What You’ll Learn
In this lesson, you’ll learn:
- what CSS transitions are;
- how to use
transition; - how to animate hover effects;
- how to use
transform; - how to use
scale; - how to use
translateY; - how to create smooth buttons and cards;
- what
@keyframesare; - how to create simple CSS animations;
- how to avoid annoying motion.
What Is a Transition?
A transition makes a CSS change happen gradually.
Without transition:
.button:hover {
background-color: #2563eb;
}
The color changes instantly.
With transition:
.button {
transition: background-color 0.2s ease;
}
.button:hover {
background-color: #2563eb;
}
Now the color changes smoothly.
The browser says:
“Relax. I will not jump. I will glide.”
That is the spirit.
Create the Project
Create a folder for this lesson:
mkdir css-lesson9
cd css-lesson9
touch index.html
touch style.css
You should have:
css-lesson9/
index.html
style.css
Open the folder in your editor.
We will build a small interactive landing page with:
- navbar;
- hero section;
- animated button;
- cards with hover effects;
- one simple keyframe animation.
Nothing too crazy.
This is not a circus.
This is a website with manners.
Write the HTML
Open index.html and add this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transitions and Simple Animations</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="hero">
<nav class="navbar">
<h1 class="logo">MotionCSS</h1>
<div class="nav-links">
<a href="#">Home</a>
<a href="#">Lessons</a>
<a href="#">Projects</a>
<a href="#">Contact</a>
</div>
</nav>
<section class="hero-content">
<p class="eyebrow">CSS Motion</p>
<h2>Make Your Interface Move Smoothly</h2>
<p>
Transitions and animations help your website feel more responsive, polished, and alive.
</p>
<a href="#" class="button">Start Moving</a>
</section>
</header>
<main class="page">
<section class="intro-card">
<h2>Movement Should Help</h2>
<p>
Good motion guides attention. Bad motion distracts users and makes the page feel nervous.
</p>
</section>
<section class="cards">
<article class="card">
<div class="icon">↗</div>
<h2>Transitions</h2>
<p>Make style changes smooth when users hover, focus, or interact.</p>
</article>
<article class="card featured">
<div class="icon">★</div>
<h2>Transforms</h2>
<p>Move, scale, rotate, and adjust elements without breaking layout.</p>
</article>
<article class="card">
<div class="icon">∞</div>
<h2>Animations</h2>
<p>Create repeated or automatic movement with keyframes.</p>
</article>
</section>
</main>
<footer class="site-footer">
<p>Created while learning CSS transitions and simple animations.</p>
</footer>
</body>
</html>
This gives us:
- hero;
- navigation;
- button;
- intro card;
- three cards;
- icons;
- footer.
Now we can make the interface move.
Carefully.
Like a ninja.
Not like a washing machine full of bricks.
Start with Base CSS
Open style.css and add:
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial, sans-serif;
background-color: #f3f4f6;
color: #111827;
}
a {
color: inherit;
text-decoration: none;
}
This gives us a clean foundation.
Now add the hero and navigation styles:
.hero {
background: linear-gradient(135deg, #111827, #312e81);
color: white;
}
.navbar {
max-width: 1100px;
margin: 0 auto;
padding: 24px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
}
.logo {
margin: 0;
font-size: 24px;
}
.nav-links {
display: flex;
gap: 20px;
font-weight: 700;
}
The page now has a dark hero and a clean navbar.
Good.
No movement yet.
The website is standing still, behaving politely.
Soon we teach it to move.
Style the Hero Content
Add this:
.hero-content {
max-width: 800px;
margin: 0 auto;
padding: 80px 24px 96px;
text-align: center;
}
.eyebrow {
margin: 0 0 16px;
color: #c4b5fd;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
}
.hero-content h2 {
margin: 0 0 20px;
font-size: 56px;
line-height: 1.1;
}
.hero-content p {
color: #ddd6fe;
font-size: 20px;
line-height: 1.7;
}
Now the hero looks like a real section.
Big heading.
Readable paragraph.
Small label.
Very professional.
Almost suspiciously calm.
Style the Button
Add this:
.button {
display: inline-block;
background-color: white;
color: #312e81;
padding: 14px 22px;
border-radius: 999px;
font-weight: 700;
margin-top: 16px;
}
The button looks fine.
But it does not react yet.
It is just sitting there.
Like a doorbell that does not make a sound.
Let us fix that.
Add a Transition
Add this to .button:
.button {
display: inline-block;
background-color: white;
color: #312e81;
padding: 14px 22px;
border-radius: 999px;
font-weight: 700;
margin-top: 16px;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
Now add hover:
.button:hover {
transform: translateY(-3px);
box-shadow: 0 14px 30px rgba(0, 0, 0, 0.25);
}
Now when you hover, the button moves up smoothly.
Important:
The transition goes on the normal state.
Not only on hover.
Correct:
.button {
transition: transform 0.2s ease;
}
.button:hover {
transform: translateY(-3px);
}
If you put transition only on hover, the effect may feel strange when the mouse leaves.
CSS is sensitive.
Like a violin.
But with semicolons.
The transition Property
The transition property can include:
property duration timing-function delay
Example:
transition: background-color 0.3s ease;
This means:
- property:
background-color; - duration:
0.3s; - timing:
ease.
You can transition multiple properties:
transition: transform 0.2s ease, box-shadow 0.2s ease;
You can also transition everything:
transition: all 0.2s ease;
But be careful with all.
It may animate things you did not expect.
CSS loves unexpected things.
Sometimes too much.
Transform
The transform property changes how an element is visually displayed.
It can move, scale, rotate, or skew an element.
Examples:
transform: translateY(-4px);
transform: scale(1.05);
transform: rotate(3deg);
Transforms are useful because they usually do not disturb the rest of the layout.
The element moves visually.
But the document flow stays stable.
This is good.
A moving element should not make the whole page panic.
Style the Page and Cards
Add this:
.page {
max-width: 1100px;
margin: 40px auto;
padding: 0 24px;
}
.intro-card {
background-color: white;
padding: 32px;
border: 2px solid #e5e7eb;
border-radius: 24px;
margin-bottom: 24px;
}
.intro-card h2 {
margin-top: 0;
}
.intro-card p {
color: #4b5563;
font-size: 18px;
line-height: 1.7;
}
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
Now style each card:
.card {
background-color: white;
padding: 28px;
border: 2px solid #e5e7eb;
border-radius: 24px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.06);
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.card h2 {
margin-top: 16px;
}
.card p {
color: #4b5563;
font-size: 18px;
line-height: 1.7;
}
The card now has a transition.
But hover still needs to be added.
Card Hover Effect
Add:
.card:hover {
transform: translateY(-6px);
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.12);
border-color: #7c3aed;
}
Now the card gently lifts when hovered.
This is a common pattern.
It tells the user:
“This element is interactive.”
But do not make the lift too large.
Bad:
transform: translateY(-40px);
That makes the card look like it is trying to leave the meeting.
Small movement is better.
Icon Animation
Style the icon:
.icon {
width: 48px;
height: 48px;
border-radius: 16px;
background-color: #ede9fe;
color: #6d28d9;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: 700;
transition: transform 0.2s ease;
}
Now make the icon move when the card is hovered:
.card:hover .icon {
transform: scale(1.1) rotate(3deg);
}
This means:
When the card is hovered, change the icon inside it.
This is useful.
The whole card reacts.
The icon reacts too.
The interface feels connected.
Like CSS finally understood teamwork.
Featured Card
Add:
.featured {
border-color: #7c3aed;
background-color: #f5f3ff;
}
Now the middle card stands out.
The page has hierarchy.
Users can see what is important.
A good design guides attention.
A bad design throws glitter and hopes for the best.
What Are Keyframes?
Transitions happen when a property changes.
Animations can run automatically.
For animations, we use @keyframes.
Example:
@keyframes float {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-8px);
}
100% {
transform: translateY(0);
}
}
This describes an animation called float.
At the start, the element is normal.
In the middle, it moves up.
At the end, it returns.
Now we can apply it.
Add a Simple Animation
Add this:
@keyframes float {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-8px);
}
100% {
transform: translateY(0);
}
}
Now apply it to the button:
.button {
animation: float 3s ease-in-out infinite;
}
This makes the button gently float forever.
But be careful.
Infinite animation can become annoying.
Use it only when it is subtle.
If your button jumps forever like it drank seven espressos, users will not thank you.
Better Use of Animation
Instead of animating the main button forever, you can animate only a small decorative element.
For example, add a floating effect to the featured icon:
.featured .icon {
animation: float 3s ease-in-out infinite;
}
This is more subtle.
The page feels alive.
But not desperate.
Good motion feels calm.
Bad motion feels like the website is trying to get your attention during a fire alarm.
Footer
Add:
.site-footer {
text-align: center;
padding: 32px 24px;
color: #6b7280;
}
Simple footer.
No animation needed.
Not everything has to move.
Seriously.
Do not animate the footer just because you can.
CSS power must be controlled.
Complete CSS
Your style.css should look like this:
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial, sans-serif;
background-color: #f3f4f6;
color: #111827;
}
a {
color: inherit;
text-decoration: none;
}
.hero {
background: linear-gradient(135deg, #111827, #312e81);
color: white;
}
.navbar {
max-width: 1100px;
margin: 0 auto;
padding: 24px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
}
.logo {
margin: 0;
font-size: 24px;
}
.nav-links {
display: flex;
gap: 20px;
font-weight: 700;
}
.hero-content {
max-width: 800px;
margin: 0 auto;
padding: 80px 24px 96px;
text-align: center;
}
.eyebrow {
margin: 0 0 16px;
color: #c4b5fd;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
}
.hero-content h2 {
margin: 0 0 20px;
font-size: 56px;
line-height: 1.1;
}
.hero-content p {
color: #ddd6fe;
font-size: 20px;
line-height: 1.7;
}
.button {
display: inline-block;
background-color: white;
color: #312e81;
padding: 14px 22px;
border-radius: 999px;
font-weight: 700;
margin-top: 16px;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.button:hover {
transform: translateY(-3px);
box-shadow: 0 14px 30px rgba(0, 0, 0, 0.25);
}
.page {
max-width: 1100px;
margin: 40px auto;
padding: 0 24px;
}
.intro-card {
background-color: white;
padding: 32px;
border: 2px solid #e5e7eb;
border-radius: 24px;
margin-bottom: 24px;
}
.intro-card h2 {
margin-top: 0;
}
.intro-card p {
color: #4b5563;
font-size: 18px;
line-height: 1.7;
}
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
.card {
background-color: white;
padding: 28px;
border: 2px solid #e5e7eb;
border-radius: 24px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.06);
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.card:hover {
transform: translateY(-6px);
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.12);
border-color: #7c3aed;
}
.card h2 {
margin-top: 16px;
}
.card p {
color: #4b5563;
font-size: 18px;
line-height: 1.7;
}
.icon {
width: 48px;
height: 48px;
border-radius: 16px;
background-color: #ede9fe;
color: #6d28d9;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: 700;
transition: transform 0.2s ease;
}
.card:hover .icon {
transform: scale(1.1) rotate(3deg);
}
.featured {
border-color: #7c3aed;
background-color: #f5f3ff;
}
@keyframes float {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-8px);
}
100% {
transform: translateY(0);
}
}
.featured .icon {
animation: float 3s ease-in-out infinite;
}
.site-footer {
text-align: center;
padding: 32px 24px;
color: #6b7280;
}
@media (max-width: 800px) {
.hero-content h2 {
font-size: 42px;
}
.cards {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 560px) {
.navbar {
flex-direction: column;
align-items: flex-start;
}
.nav-links {
flex-direction: column;
gap: 12px;
}
.hero-content {
padding: 56px 20px 72px;
text-align: left;
}
.hero-content h2 {
font-size: 34px;
}
.hero-content p {
font-size: 18px;
}
.cards {
grid-template-columns: 1fr;
}
.intro-card,
.card {
padding: 24px;
}
}
Save.
Refresh.
Hover over the button.
Hover over the cards.
Watch the featured icon float.
Your page now has motion.
Not too much.
Just enough to feel alive.
Like a professional website that had one coffee.
Not seven.
Common Mistakes
Animating Everything
Bad idea:
* {
transition: all 1s ease;
}
This can create strange effects everywhere.
Inputs.
Layout changes.
Hidden surprises.
CSS chaos in a nice coat.
Be specific.
Better:
.card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
Too Much Movement
Bad:
.card:hover {
transform: rotate(20deg) scale(1.3);
}
Unless you are building a clown portfolio, this is probably too much.
Small movement usually feels better.
.card:hover {
transform: translateY(-4px);
}
Infinite Animations Everywhere
Infinite animations can be distracting.
Use them carefully.
Good places:
- small icons;
- subtle background elements;
- loading indicators.
Bad places:
- paragraphs;
- entire sections;
- every card;
- footer;
- your soul.
Accessibility Note
Some users prefer reduced motion.
CSS supports this with:
@media (prefers-reduced-motion: reduce) {
* {
animation: none;
transition: none;
}
}
This respects users who may feel uncomfortable with motion.
You do not need to use this in every beginner exercise.
But remember it.
Good websites care about users.
Not only about looking cool.
Practice
Create three cards.
Each card should:
- lift slightly on hover;
- increase shadow on hover;
- animate an icon on hover;
- use transition;
- stay readable.
Use:
transition;transform;translateY;scale;box-shadow.
Keep motion small.
Your goal is polish.
Not panic.
Mini Challenge
Create a pricing section with three plans.
Add:
- hover lift effect on cards;
- button hover effect;
- featured plan with a subtle floating icon;
- responsive layout;
- reduced motion media query.
This is real-world CSS motion.
Small details.
Big difference.
The user may not notice every animation consciously.
But they will feel that the interface is smoother.
That is good design.
Quietly doing its job.
Summary
Today you learned:
- transitions make CSS changes smooth;
transitionshould usually be placed on the normal state;transformcan move, scale, and rotate elements;translateYis useful for hover lift effects;scalecan make icons or buttons feel interactive;box-shadowcan be animated for depth;@keyframescreates CSS animations;- infinite animations should be subtle;
- not everything needs to move;
- good motion supports usability.
Motion is powerful.
Use it carefully.
A little movement can make a website feel alive.
Too much movement makes it feel like it escaped from a cartoon.
Next Lesson
In the next lesson, we will finish the course with a complete mini project.
We will combine layout, responsive design, cards, buttons, and polished styling.
The CSS toolbox is almost ready.