CSS Animation Techniques: From Transitions to Keyframes
CSS animations bring websites to life. A subtle hover effect, a smooth page transition, or a loading spinner — these small details transform a static page into an engaging experience. The best part? You don't need JavaScript for most animations. CSS provides two powerful mechanisms: transitions for simple state changes and keyframe animations for complex, multi-step sequences. This guide covers both, plus performance optimization techniques to keep your animations silky smooth at 60fps.
CSS Transitions: The Basics
Transitions are the simplest form of CSS animation. They automatically animate the change between two states of a property. Instead of a button color snapping from blue to green instantly, a transition makes it smoothly fade over a specified duration.
.button {
background: #4A90D9;
color: white;
padding: 12px 24px;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background 0.3s ease, transform 0.2s ease;
}
.button:hover {
background: #2ECC71;
transform: translateY(-2px);
}
Transition Properties
The transition shorthand combines four sub-properties:
transition-property— Which CSS property to animate (all,background,transform, etc.)transition-duration— How long the animation takes (0.3s,200ms)transition-timing-function— The acceleration curve (ease,linear,ease-in-out,cubic-bezier())transition-delay— How long to wait before starting (0s,100ms)
Timing Functions
The timing function controls the animation's acceleration curve. The built-in options are:
ease— Starts slow, speeds up, ends slow (default)linear— Constant speed throughoutease-in— Starts slow, acceleratesease-out— Starts fast, deceleratesease-in-out— Slow start and endcubic-bezier(x1, y1, x2, y2)— Custom curve for full control
For natural-feeling motion, cubic-bezier(0.4, 0, 0.2, 1) (Material Design's standard curve) is an excellent default.
CSS Transforms
Transforms are the workhorses of CSS animation. They modify an element's visual rendering without affecting layout, making them extremely performant:
/* Move */ transform: translateX(100px); transform: translateY(-50%); transform: translate(100px, 50px); /* Scale */ transform: scale(1.5); transform: scaleX(2); /* Rotate */ transform: rotate(45deg); transform: rotate3d(1, 1, 0, 45deg); /* Skew */ transform: skewX(10deg); /* Combine multiple transforms */ transform: translateY(-10px) rotate(5deg) scale(1.1);
Keyframe Animations
For animations that need more than two states, or that should play automatically (not just on hover), use @keyframes:
@keyframes pulse {
0% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.05);
opacity: 0.8;
}
100% {
transform: scale(1);
opacity: 1;
}
}
.pulsing-element {
animation: pulse 2s ease-in-out infinite;
}
Animation Properties
The animation shorthand combines these sub-properties:
animation-name— The@keyframesnameanimation-duration— Total animation timeanimation-timing-function— Acceleration curveanimation-delay— Delay before startinganimation-iteration-count— How many times to play (1,3,infinite)animation-direction—normal,reverse,alternate,alternate-reverseanimation-fill-mode—none,forwards,backwards,bothanimation-play-state—runningorpaused
Practical Animation Examples
Loading Spinner
@keyframes spin {
to { transform: rotate(360deg); }
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid rgba(255,255,255,0.2);
border-top-color: #4A90D9;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
Fade In on Scroll
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeInUp 0.6s ease-out forwards;
}
Skeleton Loading
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
.skeleton {
background: linear-gradient(
90deg,
#1a1a2e 25%,
#2a2a4e 50%,
#1a1a2e 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s ease-in-out infinite;
border-radius: 4px;
}
Bounce Effect
@keyframes bounce {
0%, 100% { transform: translateY(0); }
25% { transform: translateY(-20px); }
50% { transform: translateY(0); }
75% { transform: translateY(-10px); }
}
.bouncing {
animation: bounce 1s ease infinite;
}
Performance Best Practices
Not all CSS properties are equal when it comes to animation performance. Animating certain properties triggers expensive browser operations:
The Golden Rule: Only Animate Transform and Opacity
These two properties are handled by the GPU compositor and don't trigger layout or paint operations:
transform— translate, scale, rotate, skewopacity— fade in/out
Avoid animating these properties (they trigger layout recalculation):
width,height,top,left,margin,paddingfont-size,border-width
Instead of animating width, use transform: scaleX(). Instead of animating top, use transform: translateY().
Use will-change Sparingly
.animated-element {
will-change: transform; /* Hints browser to optimize */
}
Don't apply will-change to everything — it uses GPU memory. Apply it only to elements that will actually animate, and remove it after animation completes if possible.
Respect User Preferences
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Some users experience motion sickness or discomfort from animations. Always include a reduced-motion media query to respect their system preferences.
CSS vs JavaScript Animation
When should you use CSS vs JavaScript for animations?
- CSS: Simple transitions, hover effects, loading states, decorative animations. Better performance for most cases.
- JavaScript: Complex sequenced animations, scroll-based animations, physics-based motion, animations that depend on user input or dynamic values.
For most UI animations — button hovers, modal appearances, skeleton loaders, tab switches — CSS is sufficient and preferred. Explore interactive examples with our Flexbox Playground and CSS Gradient Generator.
Conclusion
CSS animations are a powerful tool that every web developer should master. Start with transitions for simple hover effects, graduate to keyframes for multi-step animations, and always follow the performance golden rule: animate only transform and opacity. Respect user motion preferences with prefers-reduced-motion. Use our Box Shadow Generator and Border Radius Preview to design the elements you'll be animating, and check out our Flexbox vs Grid guide for layout techniques.
CSS Gradient Generator · Box Shadow Generator · Border Radius Preview · Flexbox Playground