By WebNest Studio Engineering Team
CSS Tutorial
CSS Transitions
Transitions let a property change smoothly over time instead of jumping instantly from one value to another, which is what makes hover effects, expanding menus, and other interactive feedback feel polished rather than abrupt. A transition is defined with a small set of properties that describe what to animate, how long it takes, and the pacing of the change.
Transitions are triggered by an actual change in a property's value — commonly caused by a pseudo-class like :hover or :focus, or by a class being toggled with JavaScript — and they only animate between a starting and ending value, unlike full keyframe animations which can define multiple intermediate steps.
Why it matters
Without a transition, a style change on hover is instant and feels abrupt. A fraction of a second of smooth change makes an interface feel responsive and shows the user what happened. Transitions are the simplest form of animation in CSS and the one you will use on almost every interactive element.
The Transition Properties
Four properties (usually combined into the transition shorthand) control the effect.
- transition-property — which CSS property to animate, e.g. background-color, transform, or all for every animatable property.
- transition-duration — how long the change takes, e.g. 0.3s or 300ms.
- transition-timing-function — the pacing curve of the change: ease (default, starts fast then slows), linear (constant speed), ease-in, ease-out, or a custom cubic-bezier().
- transition-delay — an optional pause before the transition begins.
The Shorthand and Multiple Transitions
The shorthand combines all four in one line: transition: background-color 0.3s ease-in-out;. Multiple properties can transition with different timings by comma-separating shorthand values: transition: transform 0.2s ease, opacity 0.4s linear; animates transform and opacity independently, each with its own duration and easing.
What Can Be Transitioned
Only properties with an intermediate, interpolatable value can transition smoothly — numeric values, colors, and transforms all work well. Properties like display cannot be smoothly transitioned because there's no "halfway" state between block and none. For performance, transform and opacity are the cheapest properties to animate, because they don't trigger the browser to recalculate layout the way width or top do.
Examples
A button with a smooth color and scale transition on hover
.button {
background-color: #0057d9;
transform: scale(1);
transition: background-color 0.3s ease, transform 0.2s ease-out;
}
.button:hover {
background-color: #003f9e;
transform: scale(1.05);
}
On hover, the button smoothly darkens in color over 0.3 seconds and gently scales up to 105% of its size over 0.2 seconds, rather than snapping instantly to the new values.
A delayed transition on a dropdown menu appearing
.dropdown {
opacity: 0;
visibility: hidden;
transition: opacity 0.25s ease, visibility 0.25s ease;
}
.dropdown.open {
opacity: 1;
visibility: visible;
}
When the .open class is added, the dropdown fades in smoothly over a quarter second instead of appearing instantly, and it fades back out the same way when the class is removed.
Common Mistakes
- Trying to transition display: none to display: block directly, which has no visible effect since display has no intermediate state — opacity/visibility combinations are used instead.
- Using transition: all as a lasting solution instead of just for prototyping, which can unintentionally animate properties you didn't mean to (and hurts performance).
- Forgetting that the transition must be declared on the base state (or a shared parent selector), not only inside the :hover rule, or the transition back to the original state won't animate.
- Animating layout-triggering properties like width, height, or top for frequent interactions instead of the cheaper transform and opacity, causing janky performance.
Exercise
Give the button a blue background and white text. On hover, the background becomes dark blue and the button grows slightly. Both changes should take 0.3 seconds with an ease timing.
Expected result: moving the pointer over the button darkens and enlarges it smoothly, and it returns smoothly when the pointer leaves.
/* The page contains: <main> with an <h1>, a <p> and a <button> */
button {
background-color: royalblue;
color: white;
/* TODO: transition for background-color and transform */
}
button:hover {
/* TODO: darker background, slightly larger */
}
Show hints
- The transition goes on the element itself, not on the
:hoverrule, so that it runs in both directions. - Several properties are separated by commas:
transition: background-color 0.3s ease, transform 0.3s ease.
Show solution
/* The page contains: <main> with an <h1>, a <p> and a <button> */
button {
background-color: royalblue;
color: white;
transition: background-color 0.3s ease, transform 0.3s ease;
}
button:hover {
background-color: darkblue;
transform: scale(1.05);
}
Quick quiz
1. In transition: opacity 0.5s ease-in 0.2s, what does 0.2s mean?
- A. The duration
- B. The delay before the transition starts
- C. The number of repeats
- D. The opacity value
Show answer
B. The first time value is the duration and the second is the delay.
2. On which rule should the transition property be placed?
- A. The body
- B. Only the :hover rule
- C. The base rule of the element, so that it animates both to and from the changed state
- D. A media query
Show answer
C. On :hover alone, the change back would be instant.
3. Which of these changes cannot be transitioned smoothly?
- A. opacity from 0 to 1
- B. A background colour
- C. transform: scale(1) to scale(1.2)
- D. display from none to block
Show answer
D. display has no intermediate values. Fade with opacity or visibility instead.
Interview questions
What is the difference between a transition and an animation?
Show answer
A transition animates a property between two states and needs a trigger, such as a hover or a class being added. An animation uses @keyframes to define any number of steps, can start by itself when the page loads, and can loop, alternate and pause. Transitions suit simple reactions to interaction; animations suit multi-step or continuous motion.
Which properties are best to animate for performance?
Show answer
transform and opacity. The browser can apply changes to these on the compositor without recalculating the layout or repainting, so they stay smooth. Animating properties such as width, height, top or margin forces the layout to be recalculated on every frame, which can stutter. Moving an element with translate is therefore preferred to changing its position.
Key Points to Remember
- transition-property, transition-duration, transition-timing-function, and transition-delay control how a property change animates.
- The transition shorthand combines all four, and comma-separating shorthands animates multiple properties independently.
- Only properties with interpolatable values can transition smoothly; transform and opacity are the most performance-friendly choices.
- The transition declaration should live on the base selector so it applies both when the state is entered and when it is removed.
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Shows a live preview of your HTML, CSS and JavaScript. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering