CSS Animations & Transitions: Everything You Need to Know
Master CSS animations and transitions for smooth, performant web interactions and visual effects
Overview
Master CSS animations and transitions for smooth, performant web interactions and visual effects
Reference Content
Understanding Motion in CSS
Transitions vs Animations:
- Transitions: Smooth change between two states (hover, focus, class change). Perfect for micro-interactions.
- Animations: Complex, multi-step sequences that can loop and reverse. Ideal for attention-grabbing effects.
Transitions
What it does: Smoothly animates property changes over time instead of instant jumps.
Why use it: Creates polished, professional interfaces. Users perceive smooth transitions as higher quality.
How it works:
1. Browser detects property change (hover, class addition, etc.)
2. Calculates intermediate values between start and end states
3. Updates property gradually over specified duration
.element {
/ Shorthand: property duration timing-function delay /
transition: opacity 0.3s ease-in-out 0s;/ Individual properties /
transition-property: opacity;
transition-duration: 0.3s;
transition-timing-function: ease-in-out;
transition-delay: 0s;
/ Multiple properties /
transition: opacity 0.3s, transform 0.5s;
/ All properties /
transition: all 0.3s ease;
}
Animations
/ Basic keyframes /
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}/ Percentage-based keyframes /
@keyframes slide-bounce {
0% {
transform: translateX(0);
}
25% {
transform: translateX(100px);
}
50% {
transform: translateX(100px) translateY(-20px);
}
75% {
transform: translateX(100px) translateY(0);
}
100% {
transform: translateX(0);
}
}
Common Animation Patterns
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}@keyframes spin {
to { transform: rotate(360deg); }
}
Performance Optimization
What it does: Offloads animations to GPU, achieving 60fps even on complex animations. Why it matters: Janky animations frustrate users and make apps feel broken. GPU acceleration = smooth motion. How it works:
- GPU handles:
transform,opacity,filter - CPU handles:
width,height,top,left,margin,padding - GPU creates compositor layers for animated elements
/ ✅ GOOD - GPU accelerated properties /
.performant {
transform: translateX(100px); / Position via transform /
opacity: 0.5; / Transparency /
filter: blur(5px); / Visual effects /
/ These run at 60fps without affecting other elements /
}/ ❌ AVOID - Triggers expensive layout/paint /
.expensive {
left: 100px; / Forces layout recalculation /
width: 200px; / All elements must reflow /
height: 100px; / Entire page might repaint /
/ These cause "layout thrashing" - major performance hit /
}
/ Real example: Sliding panel /
/ ❌ Bad - animates 'left' property /
.panel-slow {
position: absolute;
left: -300px;
transition: left 0.3s;
}
.panel-slow.open {
left: 0;
}
/ ✅ Good - animates 'transform' /
.panel-fast {
transform: translateX(-300px);
transition: transform 0.3s;
}
.panel-fast.open {
transform: translateX(0);
}
Common pitfall: Animating width/height for accordions. Use max-height or scale transform instead.
Performance test: Chrome DevTools > Rendering tab > Enable "Paint flashing" to see what's repainting.Interactive Examples
.flip-card {
width: 300px;
height: 200px;
perspective: 1000px;
}.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
transition: transform 0.6s;
transform-style: preserve-3d;
}
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.flip-card-back {
transform: rotateY(180deg);
}
Animation State Management
.video-animation {
animation: rotate 2s linear infinite;
animation-play-state: paused;
}.playing .video-animation {
animation-play-state: running;
}
Accessibility Considerations
What it does: Detects if users have requested reduced motion in their OS settings. Why it matters: Motion can trigger vestibular disorders, migraines, and motion sickness. It's not just preference - it's accessibility. How to implement: Provide alternatives, not just removal. Replace motion with fades or instant changes.
/ Method 1: Nuclear option - remove all motion /
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}/ Method 2: Better - provide alternatives /
.card {
animation: slideUp 0.5s ease;
}
@media (prefers-reduced-motion: reduce) {
.card {
animation: fadeIn 0.2s ease; / Gentler alternative /
}
}
/ Method 3: Best - design with preference in mind /
.animated-element {
/ Default: subtle motion /
transform: scale(1);
transition: transform 0.2s ease;
}
.animated-element:hover {
transform: scale(1.05); / Small, purposeful /
}
@media (prefers-reduced-motion: no-preference) {
/ Enhance for those who want motion /
.animated-element {
transition: transform 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
.animated-element:hover {
transform: scale(1.1) rotate(5deg);
}
}
Testing:
- macOS: System Preferences > Accessibility > Display > Reduce motion
- Windows: Settings > Ease of Access > Display > Show animations
- Chrome DevTools: Rendering tab > Emulate CSS media feature prefers-reduced-motion