CSS Transition
Learn how CSS transitions create smooth changes between property values using duration, timing functions, delays, and multiple transitions.
Introduction
In the previous lesson, you learned CSS Transform and how elements can be moved, rotated, scaled, skewed, and manipulated in two-dimensional and three-dimensional space.
However, when a CSS property changes from one value to another, the browser normally applies the new value immediately.
CSS Transition allows that change to happen gradually over a specified period of time.
A transition does not define a completely separate animation sequence. It smoothly changes a property from its current value to a new value.
What is CSS Transition?
CSS Transition is a feature that allows property values to change smoothly over a specified duration instead of changing instantly.
.button { background: #6c5ce7;}
.button:hover { background: #00b894;}Without a transition, the background color changes immediately when the pointer enters the button.
.button { background: #6c5ce7;
transition: background 0.3s ease;}
.button:hover { background: #00b894;}Without Transition
Purple ─────────────────────► Green Instant Change
With Transition
Purple ──► Blue-Purple ──► Blue-Green ──► Green 0s 0.15s 0.3sWhy Do We Need Transitions?
Instant visual changes can feel abrupt. Transitions help interfaces communicate state changes more naturally.
Smooth Changes
Change property values gradually instead of instantly.
Better Hover Effects
Create polished interactions for buttons, links, and cards.
Visual Feedback
Help users understand that an element has changed state.
Smooth Movement
Move elements naturally between positions.
Smooth Scaling
Grow or shrink elements without sudden jumps.
Professional Interfaces
Make websites feel more responsive and refined.
Instant Change
- Property changes immediately.
- Can feel abrupt.
- Movement may look like a jump.
- State changes are less polished.
Transitioned Change
- Property changes gradually.
- Movement feels smoother.
- State changes are easier to follow.
- Interface feels more polished.
Real-World Analogy
Imagine a car moving from 0 km/h to 60 km/h.
The car does not normally jump instantly from one speed to another. It accelerates over time.
| Real-World Concept | CSS Transition |
|---|---|
| Starting speed | Initial property value |
| Target speed | Final property value |
| Acceleration time | transition-duration |
| Acceleration pattern | transition-timing-function |
| Waiting before moving | transition-delay |
| What changes | transition-property |
Start
0 km/h │ ▼10 km/h │ ▼25 km/h │ ▼45 km/h │ ▼60 km/h
Final State
CSS
Initial Value │ ▼Intermediate Values │ ▼Final ValueHow Transitions Work
A transition needs an initial property value and a changed property value.
.box { width: 150px;
transition: width 1s ease;}
.box:hover { width: 300px;}Time Width
0.00s 150px0.20s 175px0.40s 210px0.60s 250px0.80s 280px1.00s 300pxYou define the starting value, final value, and transition behavior. The browser calculates the values between them.
Basic Transition Syntax
.element { transition-property: background-color;
transition-duration: 0.3s;
transition-timing-function: ease;
transition-delay: 0s;}.element { transition: background-color 0.3s ease 0s;}| Part | Purpose |
|---|---|
| transition-property | Defines which property changes smoothly |
| transition-duration | Defines how long the change takes |
| transition-timing-function | Defines the speed pattern |
| transition-delay | Defines how long to wait before starting |
Transition Properties
| Property | Purpose | Example |
|---|---|---|
| transition-property | Property to animate | transform |
| transition-duration | Length of transition | 0.3s |
| transition-timing-function | Speed curve | ease |
| transition-delay | Waiting time | 0.2s |
| transition | Shorthand for all transition values | transform 0.3s ease |
transition-property
The transition-property property defines which CSS property should change smoothly.
.button { transition-property: background-color;}.card { transition-property: transform;}.image { transition-property: opacity;}| Value | Meaning |
|---|---|
| none | No property transitions |
| all | All transitionable changed properties |
| Property name | Only the named property |
| Multiple names | Several comma-separated properties |
Example 1: Background Color
<button class="color-button"> Hover Me</button>.color-button { padding: 14px 28px;
border: none;
background-color: #6c5ce7; color: white;
border-radius: 8px;
transition-property: background-color;
transition-duration: 0.5s;}
.color-button:hover { background-color: #00b894;}Multiple Transition Properties
Several properties can be transitioned by separating their names with commas.
.card { transition-property: background-color, color, transform;
transition-duration: 0.3s;}When the state changes, only the listed properties transition smoothly.
The all Keyword
The all keyword tells the browser to transition every changed property that can be animated.
.card { transition-property: all;
transition-duration: 0.3s;}The all keyword is convenient, but explicitly listing the properties is often clearer and prevents unexpected properties from transitioning.
transition-duration
The transition-duration property defines how long a transition takes to complete.
.button { transition-duration: 0.2s;}.button { transition-duration: 2s;}| Duration | General Feeling |
|---|---|
| 0s | Instant change |
| 0.1s - 0.2s | Very fast |
| 0.2s - 0.4s | Common interface speed |
| 0.5s - 1s | Noticeably slow |
| More than 1s | Usually dramatic or demonstrative |
A transition will not appear smooth unless a duration greater than zero is provided.
Time Units
| Unit | Meaning | Example |
|---|---|---|
| s | Seconds | 0.5s |
| ms | Milliseconds | 500ms |
.one { transition-duration: 0.5s;}
.two { transition-duration: 500ms;}Both seconds and milliseconds are valid. Use the format that is easiest to read consistently in your project.
Example 2: Different Durations
<div class="duration-demo fast"> Fast</div>
<div class="duration-demo medium"> Medium</div>
<div class="duration-demo slow"> Slow</div>.duration-demo { width: 120px;
padding: 16px;
margin-bottom: 12px;
background: #6c5ce7; color: white;
border-radius: 8px;
transition-property: width;}
.duration-demo:hover { width: 300px;}
.fast { transition-duration: 0.2s;}
.medium { transition-duration: 0.7s;}
.slow { transition-duration: 2s;}transition-timing-function
The transition-timing-function property controls how the speed of a transition changes during its duration.
.box { transition-timing-function: ease-in-out;}| Value | Behavior |
|---|---|
| ease | Slow start, fast 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 steps |
ease
The ease timing function starts slowly, speeds up, and slows down again near the end.
.box { transition: transform 1s ease;}If no timing function is specified, the browser uses ease.
linear
The linear timing function keeps the transition speed constant from beginning to end.
.box { transition: transform 1s linear;}Time
0% 25% 50% 75% 100%│---------│---------│---------│---------│
Speed remains constantease-in
The ease-in timing function starts slowly and accelerates toward the end.
.box { transition: transform 1s ease-in;}Start End
Slow ─────► Faster ─────► Fastease-out
The ease-out timing function starts quickly and slows down near the end.
.box { transition: transform 1s ease-out;}Start End
Fast ─────► Slower ─────► Slowease-in-out
The ease-in-out timing function starts slowly, speeds up in the middle, and slows down again near the end.
.box { transition: transform 1s ease-in-out;}Timing Function Comparison
| Timing Function | Start | Middle | End |
|---|---|---|---|
| ease | Slow | Fast | Slow |
| linear | Constant | Constant | Constant |
| ease-in | Slow | Faster | Fast |
| ease-out | Fast | Slower | Slow |
| ease-in-out | Slow | Fast | Slow |
easeSlow ───► Fast ───► Slow
linearSame ───► Same ───► Same
ease-inSlow ───► Medium ───► Fast
ease-outFast ───► Medium ───► Slow
ease-in-outSlow ───► Fast ───► SlowExample 3: Timing Functions
<div class="track"> <div class="runner ease">ease</div></div>
<div class="track"> <div class="runner linear">linear</div></div>
<div class="track"> <div class="runner ease-in">ease-in</div></div>
<div class="track"> <div class="runner ease-out">ease-out</div></div>.track { margin-bottom: 12px;
background: #f1f2f6;
border-radius: 8px;}
.runner { width: 90px;
padding: 12px;
background: #6c5ce7; color: white;
text-align: center;
border-radius: 8px;
transition: transform 2s;}
.track:hover .runner { transform: translateX(300px);}
.ease { transition-timing-function: ease;}
.linear { transition-timing-function: linear;}
.ease-in { transition-timing-function: ease-in;}
.ease-out { transition-timing-function: ease-out;}cubic-bezier()
The cubic-bezier() function creates a custom transition speed curve.
.box { transition: transform 0.6s cubic-bezier( 0.68, -0.55, 0.27, 1.55 );}cubic-bezier( x1, y1, x2, y2)
Start Point ──► Control Point 1 Control Point 2 ──► End PointCustom cubic-bezier curves can create effects such as overshooting, bouncing-like movement, and carefully designed interface motion.
steps()
The steps() timing function divides a transition into a fixed number of jumps instead of creating continuous smooth movement.
.box { transition: transform 2s steps(4);}Start
Position 1 │ ▼Position 2 │ ▼Position 3 │ ▼Position 4 │ ▼Endsteps() is useful when a property should change in visible stages rather than through continuous interpolation.
transition-delay
The transition-delay property defines how long the browser waits before starting a transition.
.box { transition-property: transform;
transition-duration: 0.5s;
transition-delay: 1s;}Positive Delay
A positive delay waits before the transition starts.
.box { transition: transform 0.5s ease 1s;}State Change
0s ─────────────── 1s ─────────────── 1.5s│ │ │Wait Start End TransitionNegative Delay
A negative transition delay makes the transition behave as if it had already been running for part of its duration.
.box { transition: transform 2s linear -0.5s;}A negative delay starts immediately but begins from a later point in the transition progress.
Example 4: Delayed Transition
<div class="delay-box"> Hover and Wait</div>.delay-box { width: 180px;
padding: 24px;
background: #6c5ce7; color: white;
text-align: center;
border-radius: 10px;
transition: transform 0.6s ease 0.8s;}
.delay-box:hover { transform: translateX(180px);}Transition Shorthand
The transition shorthand combines the transition property name, duration, timing function, and delay into one declaration.
.element { transition: property duration timing-function delay;}.button { transition: background-color 0.3s ease 0s;}Shorthand Order
When two time values are present in the transition shorthand, the first is interpreted as the duration and the second as the delay.
.box { transition: transform 0.5s ease 1s;}| Value | Meaning |
|---|---|
| transform | Property |
| 0.5s | Duration |
| ease | Timing function |
| 1s | Delay |
If two time values are used, remember: first time is duration, second time is delay.
Example 5: Shorthand Transition
<button class="shorthand-button"> Hover Me</button>.shorthand-button { padding: 14px 28px;
border: none;
background: #6c5ce7; color: white;
border-radius: 8px;
transition: transform 0.3s ease-out;}
.shorthand-button:hover { transform: translateY(-6px) scale(1.05);}Multiple Transitions
Different properties can have different durations, timing functions, and delays by separating transition definitions with commas.
.card { transition: transform 0.3s ease, background-color 0.5s linear, box-shadow 0.4s ease-out;}Every comma-separated transition can define its own property, duration, timing function, and delay.
Example 6: Multiple Properties
<article class="multi-card"> <h3>CSS Transition</h3>
<p> Hover over this card. </p></article>.multi-card { width: 260px;
padding: 30px;
background: white;
border-radius: 14px;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
transition: transform 0.3s ease, background-color 0.5s ease, color 0.4s ease, box-shadow 0.3s ease;}
.multi-card:hover { transform: translateY(-10px);
background-color: #6c5ce7;
color: white;
box-shadow: 0 18px 40px rgba(108, 92, 231, 0.3);}Transition Trigger
A transition starts when a transitionable property changes from one value to another.
:hover
Starts when the pointer enters or leaves an element.
:focus
Starts when an element gains or loses keyboard focus.
:active
Starts while an element is being activated.
:checked
Starts when a form control changes checked state.
Class Change
Starts when JavaScript adds or removes a class.
Style Change
Starts when a property value changes dynamically.
Hover Transitions
The :hover pseudo-class is one of the most common ways to trigger a CSS transition.
.card { transform: translateY(0);
transition: transform 0.3s ease;}
.card:hover { transform: translateY(-10px);}Placing transition on the normal element allows the property to transition both when entering and leaving the changed state.
Focus Transitions
Transitions can improve focus feedback for keyboard and form interactions.
.input { border: 2px solid #dfe6e9;
box-shadow: 0 0 0 0 rgba(108, 92, 231, 0);
transition: border-color 0.3s ease, box-shadow 0.3s ease;}
.input:focus { border-color: #6c5ce7;
box-shadow: 0 0 0 4px rgba(108, 92, 231, 0.15);}Class-Based Transitions
JavaScript can add or remove a class, and CSS transitions can smoothly animate the resulting property changes.
<div class="panel" id="panel"> Menu</div>
<button id="toggleButton"> Toggle Panel</button>.panel { transform: translateX(-100%);
opacity: 0;
transition: transform 0.4s ease, opacity 0.4s ease;}
.panel.open { transform: translateX(0);
opacity: 1;}const panel = document.querySelector('#panel');
const button = document.querySelector('#toggleButton');
button.addEventListener('click', () => { panel.classList.toggle('open');});Example 7: Expanding Card
<article class="expand-card"> <div class="card-icon"> CSS </div>
<h3>Transitions</h3>
<p> Smooth property changes. </p></article>.expand-card { width: 260px;
padding: 30px;
background: white;
border-radius: 16px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
transition: transform 0.35s ease, box-shadow 0.35s ease;}
.card-icon { width: 60px; height: 60px;
display: grid;
place-items: center;
background: #6c5ce7; color: white;
border-radius: 14px;
transition: transform 0.35s ease, border-radius 0.35s ease;}
.expand-card:hover { transform: translateY(-10px) scale(1.03);
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.16);}
.expand-card:hover .card-icon { transform: rotate(10deg) scale(1.1);
border-radius: 50%;}Transitions with Transform
The transform property is one of the most commonly transitioned properties because it supports movement, rotation, and scaling.
.button { transform: translateY(0) scale(1);
transition: transform 0.3s ease;}
.button:hover { transform: translateY(-5px) scale(1.05);}For visual movement, translate() is commonly preferred over repeatedly changing layout-related properties.
Example 8: Interactive Button
<button class="action-button"> <span>Get Started</span>
<span class="arrow">→</span></button>.action-button { display: inline-flex;
align-items: center;
gap: 10px;
padding: 14px 24px;
border: none;
background: #6c5ce7; color: white;
border-radius: 10px;
cursor: pointer;
transition: transform 0.3s ease, background-color 0.3s ease, box-shadow 0.3s ease;}
.arrow { transition: transform 0.3s ease;}
.action-button:hover { transform: translateY(-4px);
background-color: #5f4dd0;
box-shadow: 0 12px 24px rgba(108, 92, 231, 0.3);}
.action-button:hover .arrow { transform: translateX(6px);}Transitions with Opacity
The opacity property is commonly transitioned to create fade-in and fade-out effects.
.message { opacity: 0;
transition: opacity 0.4s ease;}
.message.visible { opacity: 1;}An element with opacity: 0 is invisible, but it still occupies its normal layout space and may still receive pointer interaction.
Example 9: Fade Effect
<div class="image-card"> <img src="mountain.jpg" alt="Mountain" >
<div class="overlay"> <h3>Explore Nature</h3>
<p> Discover beautiful places. </p> </div></div>.image-card { position: relative;
width: 320px;
overflow: hidden;
border-radius: 16px;}
.image-card img { display: block;
width: 100%;
transition: transform 0.5s ease;}
.overlay { position: absolute;
inset: 0;
display: grid;
place-content: center;
padding: 30px;
background: rgba(45, 52, 54, 0.75);
color: white;
text-align: center;
opacity: 0;
transition: opacity 0.4s ease;}
.image-card:hover img { transform: scale(1.08);}
.image-card:hover .overlay { opacity: 1;}Properties That Can Transition
Many CSS properties can transition because the browser can calculate meaningful intermediate values between their starting and ending states.
| Category | Examples |
|---|---|
| Colors | color, background-color, border-color |
| Dimensions | width, height, max-width, max-height |
| Spacing | margin, padding, gap |
| Position | top, right, bottom, left |
| Transparency | opacity |
| Transforms | transform |
| Borders | border-width, border-radius |
| Shadows | box-shadow, text-shadow |
| Typography | font-size, letter-spacing, line-height |
Properties That Cannot Transition
Some CSS properties do not have meaningful intermediate values and therefore cannot transition smoothly in the traditional way.
| Property Change | Problem |
|---|---|
| display: none to block | No continuous intermediate display value |
| position: static to absolute | Discrete layout mode change |
| font-family changes | Different font resources cannot be smoothly interpolated |
| Some keyword values | No numeric or interpolated path between states |
Why display Cannot Transition
Traditional CSS transitions cannot smoothly interpolate between display: none and display: block because there are no meaningful intermediate display states.
.message { display: none;
transition: display 0.5s;}
.message.visible { display: block;}display: none
│ │ No Intermediate Values ▼
display: blockAlternatives to display
For common reveal and hide effects, properties such as opacity, visibility, transform, and dimensions can be combined.
.message { opacity: 0;
visibility: hidden;
transform: translateY(10px);
transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;}
.message.visible { opacity: 1;
visibility: visible;
transform: translateY(0);}Opacity creates fading, transform creates movement, and visibility can prevent an invisible element from remaining interactable.
Transition Interruption
A transition can be interrupted before it finishes.
For example, if a user moves the pointer away from a button halfway through a hover transition, the browser begins transitioning from the current intermediate value toward the original value.
Start
Scale 1 │ ▼Scale 1.05 │ │ Pointer Leaves Early ▼Reverse from Current Value │ ▼Scale 1The browser does not need to finish the first transition before moving toward a new target value.
Reversing Transitions
When the changed state is removed, the browser normally transitions the property back to its original value.
.button { transform: scale(1);
transition: transform 0.3s ease;}
.button:hover { transform: scale(1.1);}If transition is placed only inside :hover, the return to the normal state may not use the same smooth transition.
Transition Events
JavaScript can listen for events related to CSS transitions.
| Event | When It Occurs |
|---|---|
| transitionrun | Transition is created |
| transitionstart | Transition begins after delay |
| transitionend | Transition finishes |
| transitioncancel | Transition is cancelled |
transitionend Event
The transitionend event runs when a CSS transition completes.
const card = document.querySelector('.card');
card.addEventListener( 'transitionend', (event) => { console.log( 'Finished:', event.propertyName ); });If several properties transition, transitionend can fire separately for each transitioned property.
Transition Performance
Different CSS properties can require different amounts of browser rendering work when they change.
Often Better for Motion
- transform
- opacity
- Commonly handled efficiently.
- Often avoids repeated layout calculations.
Can Require More Work
- width
- height
- top and left in complex layouts
- Can trigger layout and repaint work.
.card { transition: transform 0.3s ease;}
.card:hover { transform: translateY(-10px);}When an element only needs to move visually, transitioning transform is commonly more suitable than repeatedly changing layout dimensions or positions.
prefers-reduced-motion
Some users prefer reduced motion because large or frequent movement can be uncomfortable or distracting.
.card { transition: transform 0.4s ease;}
@media ( prefers-reduced-motion: reduce) { .card { transition: none; }}Important interactions should remain understandable and usable even when motion is reduced or removed.
Complete Transition Example
The following example combines background colors, transforms, opacity, shadows, multiple transitions, delays, timing functions, and interactive child elements.
<section class="course-section"> <div class="section-heading"> <span class="lesson-badge"> Lesson 21 </span>
<h2> Master CSS Transitions </h2>
<p> Hover over the course cards to explore smooth interactions. </p> </div>
<div class="course-grid"> <article class="course-card"> <div class="course-icon"> 🎨 </div>
<span class="course-label"> Beginner </span>
<h3> Color Transitions </h3>
<p> Create smooth visual changes between different colors. </p>
<a href="#"> Explore Lesson
<span class="arrow"> → </span> </a> </article>
<article class="course-card"> <div class="course-icon"> ↗ </div>
<span class="course-label"> Intermediate </span>
<h3> Transform Transitions </h3>
<p> Move, rotate, and scale elements smoothly. </p>
<a href="#"> Explore Lesson
<span class="arrow"> → </span> </a> </article>
<article class="course-card"> <div class="course-icon"> ✨ </div>
<span class="course-label"> Advanced </span>
<h3> Custom Timing </h3>
<p> Control motion using custom timing curves. </p>
<a href="#"> Explore Lesson
<span class="arrow"> → </span> </a> </article> </div></section>.course-section { padding: 50px;
background: #f5f6fa;
border-radius: 24px;}
.section-heading { max-width: 650px;
margin-bottom: 35px;}
.lesson-badge { display: inline-block;
padding: 7px 14px;
background: #6c5ce7; color: white;
border-radius: 999px;
transition: transform 0.3s ease, background-color 0.3s ease;}
.lesson-badge:hover { transform: rotate(-4deg) scale(1.05);
background-color: #5f4dd0;}
.course-grid { display: grid;
grid-template-columns: repeat( auto-fit, minmax(220px, 1fr) );
gap: 24px;}
.course-card { position: relative;
padding: 30px;
overflow: hidden;
background: white; color: #2d3436;
border: 1px solid #dfe6e9;
border-radius: 18px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06);
transition: transform 0.35s ease, background-color 0.45s ease, color 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;}
.course-card::before { content: '';
position: absolute;
top: 0; left: 0;
width: 100%; height: 5px;
background: #6c5ce7;
transform: scaleX(0);
transform-origin: left center;
transition: transform 0.4s ease;}
.course-icon { width: 60px; height: 60px;
display: grid;
place-items: center;
margin-bottom: 20px;
background: rgba(108, 92, 231, 0.1);
border-radius: 14px;
font-size: 1.8rem;
transition: transform 0.4s cubic-bezier( 0.68, -0.55, 0.27, 1.55 ), background-color 0.3s ease;}
.course-label { display: inline-block;
margin-bottom: 10px;
color: #6c5ce7;
font-size: 0.8rem;
font-weight: 700;
transition: color 0.3s ease;}
.course-card h3 { margin-bottom: 12px;}
.course-card p { color: #636e72;
transition: color 0.35s ease;}
.course-card a { display: inline-flex;
align-items: center;
gap: 8px;
margin-top: 18px;
color: #6c5ce7;
font-weight: 600;
text-decoration: none;
transition: color 0.3s ease;}
.arrow { transition: transform 0.3s ease;}
.course-card:hover { transform: translateY(-12px);
background-color: #6c5ce7;
color: white;
border-color: #6c5ce7;
box-shadow: 0 22px 50px rgba(108, 92, 231, 0.25);}
.course-card:hover::before { transform: scaleX(1);}
.course-card:hover .course-icon { transform: rotate(8deg) scale(1.12);
background-color: white;}
.course-card:hover .course-label,.course-card:hover p,.course-card:hover a { color: white;}
.course-card:hover .arrow { transform: translateX(7px);}Browser Rendering Flow
When a transitionable property changes, the browser compares the current value with the new value and calculates intermediate values over time.
Initial State │ ▼Property Value Changes │ ▼Is Property Transitionable? │ ┌──┴──┐ │ │No Yes │ │ ▼ ▼Jump Read Transition Settings │ ▼ Apply Delay │ ▼ Start Duration │ ▼ Timing Function │ ▼Calculate Intermediate Values │ ▼Render Frames │ ▼Final StateReal-World Applications
Buttons
Create smooth hover, focus, and active states.
Cards
Lift, scale, rotate, and change shadows smoothly.
Navigation Menus
Slide menus and dropdown panels into view.
Image Galleries
Zoom images and fade overlays.
Forms
Smoothly highlight focused inputs and validation states.
Tooltips
Fade and move helpful information into view.
Toggles
Move switches and change colors smoothly.
Dashboards
Reveal panels and update interactive controls.
Advantages
Smooth Interfaces
Replace abrupt changes with gradual visual feedback.
Easy to Learn
Simple transitions require only a few CSS properties.
Better Interaction
Improve hover, focus, and active states.
Flexible Control
Control property, duration, speed curve, and delay.
Multiple Properties
Transition several properties with independent settings.
Efficient Motion
Transform and opacity transitions can provide smooth visual effects.
Automatic Reversal
Transitions naturally move back toward original values when states change.
Works with JavaScript
Class changes can trigger transitions without manually calculating frames.
Common Beginner Mistakes
The default duration is 0s, so no smooth transition will be visible.
The return to the original state may not transition as expected.
Traditional transitions cannot smoothly interpolate between display: none and display: block.
A transition needs a starting value and a changed target value.
Unexpected changed properties may begin transitioning.
Duration controls how long the transition runs, while delay controls how long it waits before starting.
The first time value is duration and the second is delay.
Values such as 0.3 require a time unit like s or ms.
Slow interface transitions can make the website feel unresponsive.
Extremely fast transitions may appear almost instant.
Unnecessary transitions can make the interface difficult to understand and maintain.
Changing dimensions can require more layout work than using transform for visual movement.
Separate transition definitions must be separated by commas.
Constant speed can feel mechanical for many interface interactions.
ease-in starts slowly and finishes faster.
ease-out starts quickly and finishes slowly.
Users should not wait unnecessarily for important interaction feedback.
Users can change state before a transition finishes.
An element with opacity: 0 may still receive interaction.
Some users prefer reduced or removed motion.
Best Practices
- Use transitions to communicate meaningful state changes.
- Keep interface transitions subtle and purposeful.
- Place transition declarations on the base element in most cases.
- Define an initial property value.
- Define a changed property value.
- Use transition-property to control exactly what changes smoothly.
- Prefer explicit property names over all when practical.
- Use all only when every changed transitionable property should animate.
- Always provide a duration greater than zero for visible transitions.
- Use seconds or milliseconds consistently.
- Remember that 1000ms equals 1s.
- Keep common interface transitions relatively short.
- Use approximately 0.2s to 0.4s for many simple interactions.
- Use longer durations only when the motion needs to be observed clearly.
- Avoid transitions that make interfaces feel slow.
- Choose timing functions based on the desired feeling.
- Use ease for general-purpose transitions.
- Use linear when constant speed is appropriate.
- Use ease-in when movement should accelerate.
- Use ease-out when movement should decelerate.
- Use ease-in-out for smooth starts and endings.
- Use cubic-bezier() when a custom motion curve is necessary.
- Keep custom timing curves understandable and consistent.
- Use steps() only when discrete movement is intentional.
- Use transition-delay carefully.
- Avoid delaying important interaction feedback.
- Remember that positive delay waits before starting.
- Remember that negative delay starts partway through the transition.
- Use the transition shorthand for concise declarations.
- Remember the shorthand order: property, duration, timing function, delay.
- Remember that the first time value is duration.
- Remember that the second time value is delay.
- Separate multiple transitions with commas.
- Give different properties different durations when appropriate.
- Keep related transition definitions grouped together.
- Use :hover transitions for pointer interactions.
- Do not rely only on :hover for important functionality.
- Use :focus and :focus-visible for keyboard interaction feedback.
- Use :active for press feedback where appropriate.
- Use class changes for state-based transitions.
- Keep JavaScript responsible for state changes and CSS responsible for visual transitions when possible.
- Use transform for visual movement.
- Use translate() instead of layout properties for simple visual motion.
- Use scale() for subtle zoom effects.
- Use rotate() for intentional rotational feedback.
- Avoid excessive scaling that causes overlap.
- Use opacity for fade effects.
- Remember that opacity: 0 elements still occupy layout space.
- Combine opacity with visibility when hidden elements should not remain interactable.
- Use transform and opacity together for polished reveal effects.
- Do not expect display: none and display: block to transition traditionally.
- Use opacity, visibility, transform, or dimensions for common reveal effects.
- Understand whether a property can be interpolated.
- Test transitions when states change rapidly.
- Expect transitions to be interrupted.
- Ensure interrupted transitions reverse naturally.
- Avoid transition effects that require users to wait before clicking.
- Keep interactive targets stable during transitions.
- Do not move buttons so far that they become difficult to click.
- Avoid large layout shifts during interaction.
- Use transform instead of width or height when only visual movement is required.
- Prefer transform and opacity for common high-frequency visual effects.
- Avoid transitioning many expensive properties simultaneously.
- Test transitions on lower-powered devices.
- Use browser developer tools to inspect active transitions.
- Check computed transition values when debugging.
- Verify that transition-property matches the property that actually changes.
- Check for overridden transition declarations.
- Check commas when defining multiple transitions.
- Check time units when a transition does not run.
- Check whether the property is transitionable.
- Keep transition durations consistent across similar components.
- Create a small motion system for larger projects.
- Use similar durations for similar interactions.
- Use consistent timing curves across related components.
- Make faster transitions for small changes.
- Use slightly longer transitions for larger movement.
- Avoid decorative motion that distracts from content.
- Do not transition every possible property.
- Use color transitions for hover and focus feedback.
- Use border-color transitions for form states.
- Use box-shadow transitions carefully.
- Use border-radius transitions only when shape change is meaningful.
- Use transitions for menus and panels without hiding essential controls.
- Ensure keyboard users can trigger equivalent state changes.
- Keep focus indicators visible during transitions.
- Do not remove outlines without providing accessible alternatives.
- Use semantic HTML beneath visual effects.
- Test transitions on touch devices.
- Remember that hover behavior differs on touch screens.
- Test transitions at narrow screen widths.
- Test transitions at large screen widths.
- Check whether transformed elements overflow their containers.
- Use overflow carefully with moving elements.
- Avoid clipping focus indicators.
- Respect prefers-reduced-motion.
- Reduce or remove non-essential motion when requested by the user.
- Keep functionality available when transitions are disabled.
- Do not depend on motion alone to communicate important information.
- Use transitionend only when code truly needs to react after completion.
- Remember that transitionend may fire once for each transitioned property.
- Handle cancelled or interrupted transitions when necessary.
- Avoid adding complex JavaScript when CSS transitions can solve the visual requirement.
- Use CSS transitions for simple two-state changes.
- Use CSS animations for multi-step or repeating sequences.
- Choose the simplest motion technique that solves the problem.
- Keep transitions smooth, short, consistent, and purposeful.
Choose what changes, decide how long it takes, control how the speed changes, and optionally decide how long to wait before starting.
Frequently Asked Questions
CSS Transition allows a property value to change smoothly over a specified duration instead of changing instantly.
They are transition-property, transition-duration, transition-timing-function, and transition-delay.
It defines which CSS property should transition smoothly.
It defines how long the transition takes to complete.
The default duration is 0s, which means the change appears instant.
Transitions commonly use seconds with s or milliseconds with ms.
One second equals 1000 milliseconds.
It controls how the transition speed changes during the duration.
The default timing function is ease.
linear keeps the transition speed constant from beginning to end.
ease-in starts slowly and accelerates toward the end.
ease-out starts quickly and slows down near the end.
ease-in-out starts slowly, speeds up in the middle, and slows down near the end.
cubic-bezier() creates a custom transition timing curve.
steps() divides a transition into a fixed number of visible jumps.
It defines how long the browser waits before starting the transition.
Yes. A negative delay starts immediately as if the transition had already been running.
It combines the property, duration, timing function, and delay into one declaration.
The common order is property, duration, timing function, and delay.
The first time value is the duration.
The second time value is the delay.
Yes. Separate multiple transition definitions with commas.
It transitions every changed property that supports interpolation.
No. Explicitly listing properties is often clearer and prevents unexpected transitions.
It is usually placed on the base element so both forward and reverse state changes transition smoothly.
Yes. Hover transitions are one of the most common uses of CSS transitions.
Yes. Focus state changes can transition properties such as border color and box shadow.
Yes. JavaScript can change classes or styles, and CSS can transition the resulting property changes.
Traditional CSS transitions cannot smoothly interpolate between these display values.
Common alternatives include opacity, visibility, transform, and dimensions.
No. The element remains in layout and may still receive interaction.
The browser transitions from the current intermediate value toward the new target value.
When the property returns to its original value, the browser can transition smoothly back.
transitionend is a JavaScript event that fires when a CSS transition finishes.
Yes. It can fire separately for each transitioned property.
transform and opacity are commonly preferred for many visual motion effects.
No, but width changes can require layout recalculation. Use transform when only visual movement or scaling is needed.
It is a media feature that allows CSS to respond when a user prefers less motion.
A transition usually moves between property states when a change occurs, while an animation can define multiple keyframes, repeat, and run automatically.
The next lesson covers CSS Animation, including @keyframes, animation properties, duration, delay, iteration count, direction, fill mode, timing functions, and practical animation examples.
Key Takeaways
- CSS transitions create smooth changes between property values.
- A transition needs an initial value and a changed value.
- transition-property defines what changes smoothly.
- transition-duration defines how long the change takes.
- The default duration is 0s.
- Time values can use seconds or milliseconds.
- transition-timing-function controls the speed pattern.
- ease starts slowly, speeds up, and slows down.
- linear uses constant speed.
- ease-in starts slowly.
- ease-out ends slowly.
- ease-in-out starts and ends slowly.
- cubic-bezier() creates custom timing curves.
- steps() creates discrete jumps.
- transition-delay controls when the transition begins.
- Positive delay waits before starting.
- Negative delay starts partway through the transition.
- The transition shorthand combines all transition settings.
- The first shorthand time value is duration.
- The second shorthand time value is delay.
- Multiple transitions are separated with commas.
- Transitions can be triggered by hover, focus, active states, and class changes.
- Transitions should normally be placed on the base element.
- Transform and opacity are commonly useful for smooth visual effects.
- Traditional transitions cannot smoothly animate display changes.
- Interrupted transitions continue from their current value.
- Transitions can automatically reverse when states change back.
- JavaScript can listen for transition events.
- prefers-reduced-motion helps respect user motion preferences.
- Transitions are best for simple state-to-state changes.
Summary
CSS Transition allows property values to change smoothly over time instead of changing instantly.
A transition requires a property value to change from an initial state to a new state.
The transition-property property defines which property should transition.
The transition-duration property defines how long the transition takes.
The transition-timing-function property controls how the speed changes during the transition.
Common timing functions include ease, linear, ease-in, ease-out, and ease-in-out.
The cubic-bezier() function creates custom timing curves, while steps() divides a transition into fixed jumps.
The transition-delay property controls how long the browser waits before starting the transition.
The transition shorthand combines the property, duration, timing function, and delay.
Multiple properties can transition independently using comma-separated transition definitions.
Transitions can be triggered by pseudo-classes such as :hover and :focus or by JavaScript class changes.
The transform and opacity properties are commonly used for smooth visual movement and fading.
Traditional transitions cannot smoothly interpolate between display: none and display: block.
Transitions can be interrupted and reversed naturally when the target state changes.
JavaScript transition events such as transitionend can detect when a transition finishes.
For accessible interfaces, non-essential motion should be reduced when the user prefers reduced motion.
CSS transitions are ideal for smooth state changes such as button hover effects, card interactions, form focus states, menus, overlays, and interface feedback.
In the next lesson, you will learn CSS Animation, including @keyframes, animation properties, duration, delays, iteration counts, directions, fill modes, timing functions, and complete animation examples.