Transitions and animations both create motion in CSS, but they solve different problems — one responds to a state change, the other runs independently on its own timeline.
/* Transition: animates a property change between two states */
.button {
background: #3858e9;
transition: background 0.2s ease, transform 0.2s ease;
}
.button:hover {
background: #183ad6;
transform: translateY(-2px);
}
/* Animation: runs on its own, with multiple keyframe steps */
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.loading-indicator {
animation: pulse 1.5s ease-in-out infinite;
}
Use a transition for simple “from state A to state B” changes (hover, focus, a toggled class), and an animation when you need multiple steps, looping, or motion that isn’t triggered by a state change at all — a loading spinner has nothing to transition from, so it needs @keyframes.