Topic 13 of 48 · Full Stack Essentials

Transition & Animations

Lesson TL;DRTopic 5: Transition & Animations 📖 11 min read · 🎯 Intermediate · 🧭 Prerequisites: jointquerynestedqueryfilteringdata, tableformspagelayoutintroduction Why this matters Up until now, every state ch...
11 min read·intermediate·css · transitions · animations · keyframes

Topic 5: Transition & Animations

📖 11 min read · 🎯 Intermediate · 🧭 Prerequisites: joint-query-nested-query-filtering-data, table-forms-page-layout-introduction

Why this matters

Up until now, every state change in your web page has been instant — click a button, and things just snap. No warning, no flow. Here's the thing — when something changes without any visual cue, users often think something broke. CSS transitions and animations fix exactly that. They turn those abrupt snaps into smooth, deliberate movements that feel intentional. A button that fades in, a menu that slides out, a color that shifts gradually — these small details are the difference between a page that feels built and one that feels finished.

What You'll Learn

  • Understand what CSS transitions are and how to configure their four core properties
  • Apply transitions to element state changes like :hover using transition shorthand
  • Define multi-step animation sequences with @keyframes
  • Set animation properties including duration, timing, iteration count, and direction
  • Combine transitions and @keyframes animations on a real navigation menu

The Analogy

Think of a traffic light at a busy Vizag intersection. Without transitions, it would switch from green to red in a single violent flash — no warning, all shock. With transitions, the amber phase eases drivers from one state to the next, buying reaction time and preventing chaos. CSS transitions are that amber phase for your UI: they don't change where things end up, only how gracefully they get there. Animations go further still — imagine a neon sign that cycles through colours on its own schedule, looping indefinitely without any user action required. That autonomous, repeating motion is exactly what @keyframes animations give you.

Chapter 1: Why Motion Matters on the Web

A static page communicates information. A page with thoughtful motion communicates intent. When a button darkens smoothly on hover, the user understands it is interactive without reading a label. When a badge pulses gently, it signals urgency without a pop-up. CSS gives us two complementary tools for motion:

  • Transitions — animate between two known states (normal → hovered, closed → open). Triggered by a change in CSS property value.
  • Animations — animate through an arbitrary sequence of states defined by @keyframes. Run automatically, on a timer, and can loop forever.

Neither requires JavaScript. Both are GPU-accelerated when applied to transform and opacity, keeping frame rates smooth.

Chapter 2: Mastering CSS Transitions

The Four Transition Properties

Every transition is described by four values that you can set individually or in the transition shorthand:

PropertyPurposeExample value
transition-propertyWhich CSS property to animatebackground, transform, all
transition-durationHow long the animation takes0.3s, 500ms
transition-timing-functionThe acceleration curveease, ease-in-out, linear, cubic-bezier(...)
transition-delayWait before starting0s, 0.2s

Shorthand Syntax

selector {
  transition: <property> <duration> <timing-function> <delay>;
}

Working Example — Button Background

.button {
  background: blue;
  transition: background 0.5s ease-in-out;
}

.button:hover {
  background: red;
}

When the cursor enters .button, the browser smoothly interpolates background from blue to red over half a second using the ease-in-out curve. When the cursor leaves, it transitions back automatically — no extra rule needed.

Common Timing Functions

/* Built-in keywords */
transition-timing-function: ease;          /* slow start, fast middle, slow end */
transition-timing-function: ease-in;       /* slow start */
transition-timing-function: ease-out;      /* slow end */
transition-timing-function: ease-in-out;   /* slow start and end */
transition-timing-function: linear;        /* constant speed */

/* Custom bezier curve */
transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);

Transitioning Multiple Properties

.card {
  transition: background-color 0.3s ease, transform 0.2s ease-out;
}

Use all as the property to catch every changing CSS value, though that can cause unintended animations — prefer listing specific properties.

Chapter 3: Diving Into CSS Animations with @keyframes

Transitions only know a start and an end. Animations know the entire journey.

Defining Keyframes

@keyframes color-change {
  from {
    background-color: red;
  }
  to {
    background-color: yellow;
  }
}

from is an alias for 0% and to is an alias for 100%. You can insert as many percentage stops as needed.

Applying the Animation

.animated-element {
  animation: color-change 2s infinite alternate;
}

This single shorthand packs four values:

PositionValueMeaning
namecolor-changeWhich @keyframes block to use
duration2sOne cycle takes 2 seconds
iteration-countinfiniteLoop forever
directionalternateEven runs go forward, odd runs reverse

The Full Animation Longhand Properties

.animated-element {
  animation-name: color-change;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-delay: 0s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
  animation-fill-mode: forwards;   /* hold final keyframe state after last run */
  animation-play-state: running;   /* or 'paused' — controllable via JS */
}

Multi-Stop Keyframes

You are not limited to two stops. Add as many percentage breakpoints as your motion requires:

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

This pulse animation scales an element up to 110% at the midpoint, then returns it to normal size — creating a heartbeat-like effect.

Chapter 4: Putting It Together — Animate Your Navigation Menu

This full task combines an HTML navigation structure, CSS transitions on hover, and a @keyframes pulse animation.

Step 0 — HTML Structure

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Animated Menu</title>
  <link rel="stylesheet" href="menu.css" />
</head>
<body>
  <nav>
    <ul>
      <li class="menu-item">Home</li>
      <li class="menu-item">About</li>
      <li class="menu-item">Services</li>
      <li class="menu-item">Contact</li>
    </ul>
  </nav>
</body>
</html>

Step 1 — Style the Menu and Add Transitions

ul {
  list-style: none;
  padding: 0;
}

.menu-item {
  display: inline-block;
  margin-right: 10px;
  padding: 10px;
  background-color: #333;
  color: white;
  transition: background-color 0.3s ease;
}

.menu-item:hover {
  background-color: #777;
}

The transition: background-color 0.3s ease rule means every time .menu-item leaves or enters :hover state, the background colour eases over 300 ms instead of snapping.

Step 2 — Add the Pulse Animation on Hover

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

.menu-item:hover {
  background-color: #777;
  animation: pulse 1s infinite;
}

Now hovering a menu item both changes its colour (via transition) and rhythmically scales it (via animation). The 1s infinite shorthand tells the browser to repeat the scale cycle for as long as the cursor stays on the element.

Complete menu.css

ul {
  list-style: none;
  padding: 0;
}

.menu-item {
  display: inline-block;
  margin-right: 10px;
  padding: 10px;
  background-color: #333;
  color: white;
  transition: background-color 0.3s ease;
}

@keyframes pulse {
  0%   { transform: scale(1);   }
  50%  { transform: scale(1.1); }
  100% { transform: scale(1);   }
}

.menu-item:hover {
  background-color: #777;
  animation: pulse 1s infinite;
}
sequenceDiagram
    participant User
    participant Browser
    participant CSS Engine

    User->>Browser: cursor enters .menu-item
    Browser->>CSS Engine: :hover state activates
    CSS Engine->>Browser: transition background-color → #777 (0.3s ease)
    CSS Engine->>Browser: start animation "pulse" (1s infinite)
    Browser->>User: element brightens + pulses

    User->>Browser: cursor leaves .menu-item
    Browser->>CSS Engine: :hover state removed
    CSS Engine->>Browser: transition background-color → #333 (0.3s ease)
    CSS Engine->>Browser: animation "pulse" stops
    Browser->>User: element dims + returns to normal scale

🧪 Try It Yourself

Task: Extend the animated menu so that each menu item slides in from the left when the page first loads.

What to build: Add a @keyframes slideIn animation that starts with the item translated -60px on the X axis (off-screen to the left) and opacity 0, ending at translateX(0) and opacity 1. Apply it to .menu-item with a 0.4s ease-out duration. Stagger each item using animation-delay — the first item gets 0s, the second 0.1s, the third 0.2s, the fourth 0.3s.

Starter snippet:

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

.menu-item {
  /* existing styles */
  animation: slideIn 0.4s ease-out forwards;
}

.menu-item:nth-child(1) { animation-delay: 0s;   }
.menu-item:nth-child(2) { animation-delay: 0.1s; }
.menu-item:nth-child(3) { animation-delay: 0.2s; }
.menu-item:nth-child(4) { animation-delay: 0.3s; }

Success criterion: When you open index.html in a browser, the four menu items should cascade in from the left one after the other within the first half-second. After they arrive, hovering any item should still trigger the pulse animation from Step 2.

🔍 Checkpoint Quiz

Q1. What is the fundamental difference between a CSS transition and a CSS animation?

A) Transitions require JavaScript; animations are pure CSS B) Transitions animate between two states triggered by a property change; animations use @keyframes to define an arbitrary sequence of states that can run independently C) Animations only work on transform and opacity; transitions work on any property D) Transitions are GPU-accelerated; animations always use the CPU

Q2. Given this CSS, what happens when the user hovers over .box?

.box {
  background-color: blue;
  transition: background-color 0.5s ease-in-out;
}

.box:hover {
  background-color: red;
}

A) The background snaps instantly to red, then fades back to blue over 0.5 s when the cursor leaves B) The background smoothly changes from blue to red over 0.5 s when hovered, and back to blue over 0.5 s when the cursor leaves C) Nothing happens; transition must be placed on the :hover rule to take effect D) The element disappears for 0.5 s then reappears red

Q3. Spot the bug: the developer wants the .logo element to cycle through the spin animation twice and then stop, holding its final rotated position. What is wrong?

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

.logo {
  animation: spin 1s linear 2;
}

A) 2 is not a valid iteration count; you must write 2 times B) The animation will snap back to rotate(0deg) after finishing because animation-fill-mode: forwards is missing C) @keyframes names cannot contain the word spin D) linear is not a valid timing function inside the shorthand

Q4. How would you pause a running CSS animation on a .card element using only CSS (no JavaScript), specifically when the user hovers over it?

A) .card:hover { animation-duration: 0s; } B) .card:hover { animation-iteration-count: 0; } C) .card:hover { animation-play-state: paused; } D) .card:hover { transition: none; }

A1. B — Transitions react to a CSS property change (like :hover toggling) and interpolate between exactly two values. Animations are self-contained sequences declared in @keyframes that can run automatically and loop indefinitely without any trigger.

A2. B — The transition property sits on the base rule, so the browser uses it in both directions: entering hover (blue → red, 0.5 s) and leaving hover (red → blue, 0.5 s). The transition does not need to be on the :hover rule to apply in both directions.

A3. B — Without animation-fill-mode: forwards, the browser discards the animation's final keyframe state when the animation ends, snapping the element back to its original transform. Adding forwards tells the browser to hold the last keyframe value after the last iteration completes.

A4. C — animation-play-state: paused freezes the animation at its current frame. Setting duration to 0s or iteration-count to 0 would skip or never start the animation rather than pausing a running one.

🪞 Recap

  • CSS transition smoothly interpolates a CSS property between two states and is defined by property, duration, timing-function, and delay.
  • CSS @keyframes animations let you choreograph multi-step motion sequences that run on their own schedule, looping and reversing independently of user interaction.
  • The animation shorthand packs name, duration, timing, delay, iteration count, direction, fill-mode, and play-state into one declaration.
  • Transitions and animations can coexist on the same element — e.g., a colour transition on hover alongside a perpetual scale pulse.
  • Keeping animations subtle (short durations, modest scale factors) respects users' attention and avoids triggering motion-sensitivity issues — always consider prefers-reduced-motion in production code.

📚 Further Reading

Like this topic? It’s one of 48 in Full Stack Essentials.

Block your seat for ₹2,500 and join the next cohort.