CSS Animations & Keyframes
While transition only animates between two states (normal and hover, for example), @keyframes defines a multi-step animation sequence that can run automatically, repeat, and reverse — without needing a triggering event.
@keyframes bounce {
0% { transform: translateY(0); }
50% { transform: translateY(-20px); }
100% { transform: translateY(0); }
}
.ball {
animation: bounce 1s ease-in-out infinite;
}
@keyframes defines named checkpoints (0%, 50%, 100%, or from/to for just two steps) describing the element's style at each point in time; the browser smoothly interpolates between them.
The animation shorthand combines several properties:
.element {
animation: bounce 1s ease-in-out infinite;
/* name | duration | timing-function | iteration-count */
animation-name: bounce;
animation-duration: 1s;
animation-iteration-count: infinite; /* or a specific number like 3 */
animation-direction: alternate; /* plays forward then backward */
animation-fill-mode: forwards; /* keeps the final keyframe's styles after finishing */
}
iteration-count— how many times the animation repeats;infiniteloops forever, useful for loading spinners.direction: alternate— plays forward, then backward, then forward again, avoiding an abrupt jump back to the start on each loop.fill-mode: forwards— without it, an element snaps back to its pre-animation styles the instant the animation ends, which can look like a glitch for entrance animations meant to leave the element in its final state.
A practical rule of thumb: use transition for simple two-state changes triggered by user interaction (hover, focus, a class toggle), and reach for @keyframes when you need a self-running, multi-step, or looping animation — like a spinner, a pulsing badge, or an entrance effect that plays on page load.