Create smooth animations between property changes with timing and easing functions
CSS Transitions allow you to change property values smoothly over a specified duration. Instead of instant changes, transitions create smooth, animated effects that enhance user experience and make interfaces feel more polished and responsive.
Specifies which CSS property to animate.
/* Single property */
.element {
transition-property: background-color;
}
/* Multiple properties */
.element {
transition-property: width, height, background-color;
}
/* All animatable properties */
.element {
transition-property: all;
}
/* Specific properties only */
.element {
transition-property: transform, opacity;
}
Sets how long the transition takes to complete.
/* Duration in seconds */
.element {
transition-duration: 0.3s; /* 300 milliseconds */
transition-duration: 1s; /* 1 second */
transition-duration: 2.5s; /* 2.5 seconds */
}
/* Duration in milliseconds */
.element {
transition-duration: 300ms;
transition-duration: 1000ms;
}
/* Multiple durations for multiple properties */
.element {
transition-property: width, opacity;
transition-duration: 0.5s, 1s;
}
Controls the speed curve of the transition.
/* Predefined timing functions */
.element {
transition-timing-function: ease; /* Default - slow start, fast, slow end */
transition-timing-function: linear; /* Constant speed */
transition-timing-function: ease-in; /* Slow start */
transition-timing-function: ease-out; /* Slow end */
transition-timing-function: ease-in-out; /* Slow start and end */
}
/* Custom cubic-bezier curves */
.element {
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); /* Bounce */
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1); /* Custom */
}
/* Step functions */
.element {
transition-timing-function: steps(4, end); /* 4 steps */
transition-timing-function: step-start; /* Jump to end immediately */
transition-timing-function: step-end; /* Stay at start, jump at end */
}
Delays the start of the transition.
/* Delay before transition starts */
.element {
transition-delay: 0s; /* No delay (default) */
transition-delay: 0.5s; /* 500ms delay */
transition-delay: 1s; /* 1 second delay */
}
/* Negative delay (starts partway through) */
.element {
transition-delay: -0.5s;
}
/* Multiple delays */
.element {
transition-property: width, opacity;
transition-delay: 0s, 0.3s; /* Opacity starts 0.3s after width */
}
Combine all transition properties in one declaration.
/* Shorthand syntax: property duration timing-function delay */
.element {
transition: background-color 0.3s ease 0s;
}
/* Simplified (duration is required) */
.element {
transition: all 0.3s;
}
/* With timing function */
.element {
transition: transform 0.5s ease-in-out;
}
/* With delay */
.element {
transition: opacity 0.4s ease 0.2s;
}
/* Multiple transitions (comma-separated) */
.element {
transition: width 0.3s ease,
height 0.3s ease 0.1s,
background-color 0.5s linear;
}
/* Common pattern */
.button {
transition: all 0.3s ease;
}
.button:hover {
background-color: #3498db;
transform: translateY(-3px);
box-shadow: 0 10px 20px rgba(0,0,0,0.2);
}
While transition: all is convenient, it can cause performance issues. Specify exact properties when possible for better performance.
Linear - Constant Speed
Ease - Slow Start & End (Default)
Ease-In - Slow Start
Ease-Out - Slow End
Ease-In-Out - Slow Start & End
Click any box to see the timing function in action!
/* Color Properties */
.element {
transition: background-color 0.3s,
color 0.3s,
border-color 0.3s;
}
/* Transform Properties */
.element {
transition: transform 0.4s ease;
}
/* Opacity & Visibility */
.element {
transition: opacity 0.3s,
visibility 0.3s;
}
/* Box Model Properties */
.element {
transition: width 0.3s,
height 0.3s,
padding 0.3s,
margin 0.3s;
}
/* Position Properties */
.element {
transition: top 0.3s,
left 0.3s,
right 0.3s,
bottom 0.3s;
}
/* Shadow & Outline */
.element {
transition: box-shadow 0.3s,
text-shadow 0.3s,
outline 0.3s;
}
/* Filter Effects */
.element {
transition: filter 0.3s;
}
For best performance, prefer transitioning:
Avoid transitioning layout properties (width, height, margin, padding) when possible, as they trigger reflow.
.button {
background-color: #3498db;
color: white;
padding: 12px 24px;
border: none;
border-radius: 5px;
transition: background-color 0.3s ease,
transform 0.2s ease,
box-shadow 0.3s ease;
}
.button:hover {
background-color: #2980b9;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
.button:active {
transform: translateY(0);
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
.card {
width: 300px;
height: 200px;
background: white;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
.card:hover {
transform: scale(1.05);
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
}
.nav-menu {
position: fixed;
top: 0;
left: 0;
width: 250px;
height: 100vh;
background: #2c3e50;
transform: translateX(-100%);
transition: transform 0.3s ease-in-out;
}
.nav-menu.open {
transform: translateX(0);
}
.nav-menu a {
display: block;
padding: 15px;
color: white;
transition: background-color 0.2s,
padding-left 0.2s;
}
.nav-menu a:hover {
background-color: #34495e;
padding-left: 25px;
}
.image-container {
position: relative;
overflow: hidden;
border-radius: 10px;
}
.image-container img {
width: 100%;
transition: transform 0.5s ease;
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.image-container:hover img {
transform: scale(1.2);
}
.image-container:hover .image-overlay {
opacity: 1;
}
.dropdown {
position: relative;
}
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
background: white;
border-radius: 5px;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: opacity 0.3s ease,
visibility 0.3s ease,
transform 0.3s ease;
}
.dropdown:hover .dropdown-menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
Lift Effect
Bounce & Rotate
Morph Shape
/* Delay each child element */
.list-item {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.3s ease,
transform 0.3s ease;
}
.list-item:nth-child(1) { transition-delay: 0.1s; }
.list-item:nth-child(2) { transition-delay: 0.2s; }
.list-item:nth-child(3) { transition-delay: 0.3s; }
.list-item:nth-child(4) { transition-delay: 0.4s; }
.list.visible .list-item {
opacity: 1;
transform: translateY(0);
}
// Listen for transition end
element.addEventListener('transitionend', (event) => {
console.log(`${event.propertyName} transition completed`);
});
// Trigger transition with JavaScript
element.classList.add('active');
/* CSS */
.element {
opacity: 0;
transition: opacity 0.5s ease;
}
.element.active {
opacity: 1;
}
/* Different timing for hover in and out */
.button {
background-color: #3498db;
transition: background-color 0.3s ease;
}
.button:hover {
background-color: #2980b9;
transition: background-color 0.1s ease; /* Faster on hover */
}
/* ❌ Won't work */
.element {
height: 0;
transition: height 0.3s;
}
.element.expanded {
height: auto; /* Can't transition to auto */
}
/* ✅ Solution: Use max-height */
.element {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.element.expanded {
max-height: 500px; /* Larger than content */
}
/* ❌ Won't animate */
.element {
display: none;
opacity: 0;
transition: opacity 0.3s;
}
.element.visible {
display: block;
opacity: 1;
}
/* ✅ Solution: Use visibility or position */
.element {
visibility: hidden;
opacity: 0;
transition: opacity 0.3s, visibility 0.3s;
}
.element.visible {
visibility: visible;
opacity: 1;
}
/* ❌ Causes reflow */
.element {
transition: width 0.3s, height 0.3s;
}
/* ✅ Better performance */
.element {
transition: transform 0.3s, opacity 0.3s;
}
.element:hover {
transform: scale(1.1); /* GPU accelerated */
}
Q1: What is the correct shorthand syntax for transitions?
Q2: Which timing function provides constant speed?
Q3: Which properties are best for performance when transitioning?
Q4: Can you transition the display property?
Q5: What does transition-delay do?
transition: property duration timing-function delayAlways prefer transitioning transform and opacity. They're GPU-accelerated and won't cause layout recalculation.
Instead of "transition: all", specify exact properties for better performance and control.
Choose appropriate timing functions: ease-out for entrances, ease-in for exits, ease-in-out for looping.
Transitions make interfaces feel responsive and polished. Use 200-400ms for most UI interactions.
/* Basic Pattern */
.element {
transition: property duration timing-function delay;
}
/* Common Durations */
Quick: 0.15s - 0.2s (micro-interactions)
Normal: 0.3s - 0.4s (standard UI)
Slow: 0.5s - 0.8s (emphasis)
/* Popular Timing Functions */
ease: slow start, fast middle, slow end (default)
linear: constant speed
ease-in: slow start, fast end
ease-out: fast start, slow end
ease-in-out: slow start and end
/* Performance-Friendly Properties */
✅ transform
✅ opacity
✅ filter
❌ width, height (causes reflow)
❌ margin, padding (causes reflow)
❌ top, left, right, bottom (causes reflow)
/* Common Patterns */
/* Hover lift */
transition: transform 0.3s ease, box-shadow 0.3s ease;
/* Fade in/out */
transition: opacity 0.3s ease, visibility 0.3s ease;
/* Color change */
transition: background-color 0.3s ease, color 0.3s ease;
/* Scale effect */
transition: transform 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
/* Slide menu */
transition: transform 0.3s ease-in-out;
/* Respect user preferences for reduced motion */
@media (prefers-reduced-motion: reduce) {
* {
transition-duration: 0.01ms !important;
animation-duration: 0.01ms !important;
}
}
/* Or disable completely */
@media (prefers-reduced-motion: reduce) {
* {
transition: none !important;
animation: none !important;
}
}