CSS Animations & Transitions Cheat Sheet
Covers CSS transitions, @keyframes animations, transform functions, and performance-conscious animation properties for smooth UI motion.
CSS Transitions
Animating property changes between states.
.button { background: #3498db; transition: background-color 0.3s ease, transform 0.2s ease-out;}.button:hover { background-color: #2980b9; transform: translateY(-2px);}/* transition shorthand: property duration timing-function delay */.card { transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) 0s;}
@keyframes Animations
Multi-step animations independent of state changes.
@keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); }}.toast { animation: fadeInUp 0.4s ease-out forwards;}@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); }}.spinner { animation: spin 1s linear infinite;}
Transform Functions
Moving, scaling, and rotating elements.
.el { transform: translate(10px, 20px); /* move on x/y */ transform: scale(1.2); /* uniform scale */ transform: rotate(45deg); transform: skew(10deg, 0deg); transform: translate3d(0, 0, 0); /* promote to its own GPU layer */ /* combine multiple functions, applied left to right */ transform: translateX(10px) rotate(5deg) scale(1.1); transform-origin: center center; /* pivot point for scale/rotate */}
Animation Properties
Fine-tuning timing and behavior.
- animation-duration- how long one cycle of the animation takes
- animation-timing-function- the easing curve, e.g. ease, linear, or cubic-bezier()
- animation-iteration-count- number of repeats, or infinite
- animation-fill-mode: forwards- retains the last keyframe's styles after the animation finishes
- animation-play-state- pause/running control, toggleable from JavaScript
- will-change: transform- hints to the browser to optimize ahead of an upcoming animation
- prefers-reduced-motion- media query used to respect users who have disabled motion
@property for Animatable Custom Properties
Registering a custom property's syntax and type so the browser can interpolate it, unlike plain --vars.
@property --gradient-angle { syntax: '<angle>'; initial-value: 0deg; inherits: false;}.spinner-bg { background: conic-gradient(from var(--gradient-angle), #6366f1, #ec4899, #6366f1); animation: spin-angle 3s linear infinite;}@keyframes spin-angle { to { --gradient-angle: 360deg; }}
Scroll-Driven Animations
Tying animation progress to scroll position with no JavaScript scroll listener.
/* progress bar tied to whole-document scroll */.progress-bar { animation: grow-progress linear; animation-timeline: scroll(root);}@keyframes grow-progress { from { transform: scaleX(0); } to { transform: scaleX(1); }}/* fade an element in as it enters the viewport */.reveal { animation: fade-in linear both; animation-timeline: view(); animation-range: entry 0% cover 40%;}@keyframes fade-in { from { opacity: 0; translate: 0 30px; } to { opacity: 1; translate: 0 0; }}
View Transitions API
Cross-fading DOM state changes (including SPA route swaps) with automatic snapshot diffing.
/* JS: document.startViewTransition(() => updateTheDOM()); */::view-transition-old(root),::view-transition-new(root) { animation-duration: 0.4s;}.card { view-transition-name: var(--card-id); /* unique per card enables a shared-element morph */}::view-transition-old(root) { animation-name: fade-out; }::view-transition-new(root) { animation-name: fade-in; }
Advanced Animation Vocabulary
Concepts beyond basic transitions and keyframes.
- animation-composition- controls how multiple simultaneous animations on the same property combine: replace, add, or accumulate
- transition-behavior: allow-discrete- lets you transition discrete properties like display or content-visibility, e.g. cross-fading an element out before it leaves the layout
- animation-timeline: scroll() / view()- drives animation progress from a scrollable ancestor or an element's visibility within the viewport instead of wall-clock time
- linear() easing function- defines a custom piecewise-linear easing curve for effects like bounce or spring that cubic-bezier() can't express
- @property- registers a custom property with a type, initial value, and inheritance so it can be smoothly animated/interpolated
- will-change caveats- overusing it creates persistent compositor layers that consume GPU memory; apply it shortly before the animation starts and remove it after
- prefers-reduced-motion- media feature to swap animated transforms for opacity-only or instant state changes for motion-sensitive users
Staggered List Animation
Delaying each item's entrance using a CSS counter or custom property, no JS loop required.
.list-item { opacity: 0; animation: slide-in 0.4s ease-out forwards; animation-delay: calc(var(--i) * 60ms);}@keyframes slide-in { from { opacity: 0; transform: translateX(-12px); } to { opacity: 1; transform: translateX(0); }}/* set --i per item, e.g. via nth-child or an inline style from JS */.list-item:nth-child(1) { --i: 0; }.list-item:nth-child(2) { --i: 1; }.list-item:nth-child(3) { --i: 2; }
Animate only transform and opacity when possible: they can run on the browser's compositor thread without triggering layout or paint, which is the difference between a smooth 60fps animation and a janky one.