CSS Animations: A Complete Guide
CSS animations turn static interfaces into engaging experiences. A well-timed hover effect, a smooth page transition, or a subtle loading indicator communicates polish — all with pure CSS, no JavaScript required.
CSS Transitions
Transitions are the simplest CSS animation. They define how a property changes from one value to another on a state change (like hover or focus).
.button {
background-color: blue;
transition: background-color 0.3s ease;
---
.button:hover {
background-color: darkblue;
---The Transition Shorthand
.element {
transition: property duration easing delay;
---The four parts: property (or all), duration, easing (default ease), and delay (optional).
.button {
transition: transform 0.2s ease, box-shadow 0.3s ease-in-out 0.1s;
---This animates transform over 0.2s. When the state changes, box-shadow starts after a 0.1s delay and animates for 0.3s with ease-in-out.
Easing Functions
| Value | Behavior |
|---|---|
ease | Fast start, 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, fast middle |
cubic-bezier(n, n, n, n) | Custom curve |
A custom cubic bezier gives you precise control:
.element {
transition: transform 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55);
---This creates a bounce effect where the element overshoots its final position and snaps back — a pop-in animation that feels lively without being distracting.
What Properties Can You Transition?
Not all CSS properties are animatable. Properties that define dimensions, positions, colors, and transforms work. Properties like display, font-family, or visibility (binary) do not smoothly transition.
Animatable: opacity, transform, color, background-color, width, height, margin, padding, border-radius, box-shadow, filter
Not animatable: display, font-family, position, visibility (use opacity + pointer-events instead)
CSS Keyframe Animations
When you need more than a simple A-to-B transition, keyframe animations give you full control over intermediate states.
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
---
.element {
animation: fadeIn 0.5s ease forwards;
---Multiple Keyframes
@keyframes bounce {
0% { transform: translateY(0); }
30% { transform: translateY(-30px); }
50% { transform: translateY(-15px); }
70% { transform: translateY(-5px); }
100% { transform: translateY(0); }
---The Animation Shorthand
.element {
animation: name duration easing delay iteration-count direction fill-mode;
---
.element {
animation: bounce 1s ease-in-out 0.5s infinite alternate forwards;
---Breaking this down:
| Part | Value | Meaning |
|---|---|---|
name | bounce | The @keyframes name |
duration | 1s | One full cycle |
easing | ease-in-out | Acceleration curve |
delay | 0.5s | Wait before starting |
iteration-count | infinite | Loop forever |
direction | alternate | Reverse on every other cycle |
fill-mode | forwards | Keep final state when done |
Fill Modes Explained
none(default) — Snaps back when doneforwards— Keeps the last keyframe’s stylesbackwards— Applies first keyframe during delayboth— Combines forwards and backwards
Fill mode is essential for entrance animations. Without forwards, an opacity animation from 0 to 1 would snap the element back to invisible when done.
Transforms
Transforms modify the position, rotation, scale, and skew of an element. They are the most performant CSS property for animation because they do not trigger layout recalculation — the browser handles them entirely on the compositor thread.
/* Scale */
.element:hover {
transform: scale(1.1);
---
/* Rotate */
.element:hover {
transform: rotate(45deg);
---
/* Translate (move) */
.element:hover {
transform: translateX(20px);
---
/* Skew */
.element:hover {
transform: skew(5deg, 5deg);
---
/* Combine multiple transforms */
.element:hover {
transform: translateY(-5px) scale(1.05) rotate(-2deg);
---transform-origin
Controls the pivot point of a transform. The default is center, but you can change it:
.element {
transform-origin: top left;
transform: scale(0.5);
---
.pendulum {
transform-origin: top center;
animation: swing 2s ease-in-out infinite alternate;
---
@keyframes swing {
from { transform: rotate(-15deg); }
to { transform: rotate(15deg); }
---Practical Animation Patterns
Fade In
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
---
.card {
animation: fadeIn 0.4s ease forwards;
---Combining opacity and translate creates a natural reveal effect. Pure opacity fades can feel flat; adding a slight vertical movement makes the element feel like it is rising into place.
Staggered Animation
.card:nth-child(1) { animation-delay: 0s; }
.card:nth-child(2) { animation-delay: 0.1s; }
.card:nth-child(3) { animation-delay: 0.2s; }
.card:nth-child(4) { animation-delay: 0.3s; }A staggered delay creates a ripple effect where items animate one after another. The total delay range should be under 0.5 seconds — longer delays make the page feel slow.
Loading Spinner
@keyframes spin {
to { transform: rotate(360deg); }
---
.spinner {
width: 40px;
height: 40px;
border: 4px solid #ddd;
border-top-color: blue;
border-radius: 50%;
animation: spin 0.8s linear infinite;
---Hover Lift Effect
.card {
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.3s ease;
---
.card:hover {
transform: translateY(-8px) scale(1.02);
box-shadow: 0 12px 30px rgba(0,0,0,0.15);
---The cubic-bezier with an overshoot creates a playful spring effect. The card lifts, scales slightly, and casts a deeper shadow — a classic card interaction that feels responsive and tactile.
Skeleton Screen
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
---
.skeleton {
background: linear-gradient(90deg, #eee 25%, #f5f5f5 50%, #eee 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
---Performance Optimization
Only animate opacity and transforms — the browser handles these on the compositor thread. Animating width, height, or margin triggers layout recalculations.
/* Bad — triggers layout */
.element { transition: width 0.3s, left 0.3s; }
/* Good — composited */
.element { transition: transform 0.3s, opacity 0.3s; }Use will-change: transform, opacity to hint optimization, but apply it sparingly.
Reduce Motion for Accessibility
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
---Related: Learn CSS Flexbox, CSS Grid, and responsive design.
Animation Performance
CSS animations run on the compositor thread, not the main thread, making them more performant than JavaScript animations for most use cases. The properties that trigger compositing are transform and opacity — animating width, height, top, or left triggers layout recalculations that degrade performance. Use will-change to hint to the browser about elements that will animate, but do not overuse it as it consumes memory.
Web Animations API
The Web Animations API (element.animate()) provides JavaScript control over CSS animations. It supports dynamic timing, playback control (pause, reverse, seek), and promise-based completion callbacks. Unlike CSS animations, it allows runtime-generated keyframes and timing functions. Use CSS animations for declarative, self-contained motion and the Web Animations API for dynamic, programmatic animations.
Web Performance Metrics
Understanding performance metrics helps prioritize optimization efforts. First Contentful Paint (FCP): when the first text or image appears — target under 1.8 seconds. Largest Contentful Paint (LCP): when the main content loads — target under 2.5 seconds. Interaction to Next Paint (INP): responsiveness to user interactions — target under 200 milliseconds. Cumulative Layout Shift (CLS): visual stability — target under 0.1. First Input Delay (FID): time to first interaction — target under 100 milliseconds. Time to First Byte (TTFB): server response time — target under 800 milliseconds. Use Google’s Lighthouse, WebPageTest, and Chrome DevTools to measure these metrics. Real User Monitoring (RUM) captures actual user experiences, which may differ from synthetic tests. Set up dashboards tracking Core Web Vitals and alert when thresholds are breached.
Accessibility Beyond Compliance
Web accessibility ensures your site works for everyone, including people using screen readers, keyboard navigation, or other assistive technologies. WCAG 2.2 guidelines organize requirements into four principles: Perceivable (content must be available to senses), Operable (interface must be usable), Understandable (content and interface must be comprehensible), and Robust (content must work with current and future technologies). Practical steps: use semantic HTML elements (nav, main, aside, article), provide alt text for images, ensure color contrast ratios meet WCAG AA standards (4.5:1 for normal text), support keyboard navigation with visible focus indicators, and test with screen readers (NVDA, VoiceOver, JAWS). Accessibility benefits everyone — captions help users in noisy environments, keyboard navigation helps users with repetitive strain injuries, and high contrast helps users in bright sunlight.
FAQ
What level of expertise is required? The content assumes basic programming knowledge but explains concepts in depth. Beginners may need to reference prerequisite topics.
How do I know if I am implementing this correctly? Write tests that verify behavior, use linters and static analysis, and get code reviews from experienced practitioners.
What are the most common pitfalls? Over-engineering, premature optimization, and neglecting testing are the most frequent mistakes. Start simple, measure, and iterate.
Related Concepts and Further Reading
Understanding css animations requires familiarity with several interconnected ideas and principles that together form a complete picture. Exploring these related concepts deepens your knowledge and provides context that makes the core material more meaningful and applicable. Each concept builds on the others, creating a web of understanding that supports deeper learning and practical application. Taking time to explore how these elements connect reveals patterns that accelerate comprehension and retention of new information.
The relationship between css animations and adjacent fields is worth particular attention. Many of the most important insights emerge at the boundaries between disciplines, where ideas from different areas combine to create new approaches and solutions that neither field could produce alone. Exploring these connections pays dividends in both breadth and depth of understanding, revealing patterns and principles that might otherwise remain hidden from view. Cross-disciplinary knowledge is increasingly valued as problems become more complex and interconnected.
For those looking to go beyond introductory material, several excellent resources provide deeper treatment of specific aspects of css animations. Academic journals, industry publications, authoritative reference works, and online courses each offer different perspectives and levels of detail. The key is to match your reading to your current learning goals and build knowledge progressively, focusing on quality over quantity in your study materials. A well-chosen resource that matches your current level is worth more than dozens of resources that are too basic or too advanced.