CSS Transitions
Smooth state changes that make your UI feel alive. Master the art of animating between CSS property values with timing, easing, and performance in mind.
Transition Basics
Transitions let you smoothly animate changes between CSS property values. Instead of an instant jump from one state to another, transitions create a smooth visual flow that feels natural and polished.
.box {
background-color: #2563eb;
transform: scale(1);
/* property | duration | timing-function | delay */
transition: all 0.3s ease 0s;
}
.box:hover {
background-color: #7c3aed;
transform: scale(1.1);
}
The transition property is shorthand for four individual properties:
- transition-property: Which CSS properties to animate (or
all) - transition-duration: How long the transition takes (e.g., 0.3s)
- transition-timing-function: The easing curve (e.g., ease, linear)
- transition-delay: Wait time before starting (default: 0s)
Timing Functions
Timing functions control the acceleration curve of your transition. They determine whether the animation starts slow and speeds up, or starts fast and slows down. Choose the right easing for the right context.
/* Built-in timing functions */
.linear { transition-timing-function: linear; }
.ease { transition-timing-function: ease; } /* default */
.ease-in { transition-timing-function: ease-in; } /* slow start */
.ease-out { transition-timing-function: ease-out; } /* slow end */
.ease-in-out { transition-timing-function: ease-in-out; }
/* Custom cubic-bezier curves */
.custom {
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
/* bounce effect */
}
Choosing the Right Timing Function
- linear: Constant speed - good for continuous motion like loading spinners
- ease: Starts fast, ends slow - the default, works for most cases
- ease-in: Starts slow, accelerates - good for objects exiting the screen
- ease-out: Starts fast, decelerates - good for objects entering the screen
- ease-in-out: Slow start and end - good for attention-grabbing effects
For custom curves, use cubic-bezier.com to visualize and create your own timing functions.
Transitioning Multiple Properties
You can transition multiple properties at once, each with its own duration and timing. This creates rich, layered effects that feel premium and well-crafted.
Hover Me
Multiple properties transition together
.card {
background: white;
transform: translateY(0) scale(1);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
opacity: 0.9;
/* Different durations for each property */
transition:
transform 0.3s ease-out,
box-shadow 0.3s ease-out,
background 0.5s ease,
opacity 0.2s ease;
}
.card:hover {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
transform: translateY(-8px) scale(1.02);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
opacity: 1;
}
Pro tip: While transition: all is convenient during prototyping, it's better to specify individual properties in production. This gives you fine control over timing and avoids unintended transitions on properties you didn't mean to animate.
Real-World Examples
Transitions shine in everyday UI patterns. Here are some practical applications you'll use constantly.
Button Hover States
.button {
padding: 12px 24px;
border: 2px solid #2563eb;
background: #2563eb;
color: white;
transition: all 0.2s ease;
}
.button:hover {
background: #1d4ed8;
border-color: #1d4ed8;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
}
.button:active {
transform: translateY(0);
box-shadow: 0 2px 4px rgba(37, 99, 235, 0.2);
}
Navigation Menus
.nav-link {
position: relative;
color: #64748b;
transition: color 0.2s ease;
}
.nav-link::after {
content: '';
position: absolute;
bottom: -4px;
left: 0;
width: 0;
height: 2px;
background: #2563eb;
transition: width 0.3s ease;
}
.nav-link:hover {
color: #2563eb;
}
.nav-link:hover::after {
width: 100%;
}
Image Hover Effects
.image-card {
position: relative;
overflow: hidden;
}
.image-card img {
transition: transform 0.4s ease;
}
.image-overlay {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.7);
opacity: 0;
transition: opacity 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
}
.image-card:hover img {
transform: scale(1.1);
}
.image-card:hover .image-overlay {
opacity: 1;
}
Performance & Best Practices
Not all CSS properties are created equal when it comes to animation performance. Some trigger expensive layout recalculations, while others can be GPU-accelerated for buttery smooth transitions.
Properties to Prefer (GPU-accelerated)
transform- translate, scale, rotate, skewopacity- fade in/out effects
Properties to Avoid Animating (Expensive)
width/height- triggers layout recalculationtop/left- usetransform: translate()insteadmargin/padding- affects layout
Accessibility Considerations
Some users prefer reduced motion. Respect their preferences with a media query:
/* Default transitions */
.element {
transition: transform 0.3s ease;
}
/* Disable for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
.element {
transition: none;
}
}
When to Use Transitions vs Animations
Use Transitions when: You're animating between two states (like hover effects, toggles, or UI feedback).
Use Animations when: You need complex, multi-step sequences, looping effects, or animations that start automatically. Check out the Animations page for more on keyframe animations.
Transition Delays & Staggering
The transition-delay property lets you wait before starting a transition. This is perfect for creating staggered animations where elements appear one after another.
Hover over the container to see staggered transitions
.stagger-box {
opacity: 0.3;
transform: translateY(20px);
transition: all 0.4s ease;
}
/* Stagger delays for each box */
.stagger-box:nth-child(1) { transition-delay: 0s; }
.stagger-box:nth-child(2) { transition-delay: 0.1s; }
.stagger-box:nth-child(3) { transition-delay: 0.2s; }
.stagger-box:nth-child(4) { transition-delay: 0.3s; }
.stagger-box:nth-child(5) { transition-delay: 0.4s; }
.stagger-container:hover .stagger-box {
opacity: 1;
transform: translateY(0);
}