🎬 CSS Keyframes Animation Generator
Pick a motion type, duration, easing and repeat count to build a @keyframes CSS animation snippet.
The two halves of the output
You get a named @keyframes block and a rule that applies it. Bounce
at the defaults is:
@keyframes smo-bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}
.element {
animation: smo-bounce 1.5s ease infinite;
}
The shorthand order is name, duration, timing function, iteration count. Each
easing keyword is a fixed cubic bezier: ease is
cubic-bezier(0.25, 0.1, 0.25, 1), ease-in is (0.42, 0, 1, 1),
ease-out is (0, 0, 0.58, 1) and ease-in-out is
(0.42, 0, 0.58, 1). Those curves are applied between each pair of keyframes, not
once across the whole animation - so bounce eases twice per cycle, up and back.
Rename .element to your own selector; it is a placeholder.
Choosing duration and repeat
- Loops want linear. Spin with
easevisibly hesitates at the top of each turn. Set easing to linear for anything that runs continuously. - Entrances want once. Fade and slide read as a one-time arrival; leaving repeat on infinite makes them flash.
- 0.2-0.4s for interface feedback, 1-2s for ambient motion. The 1.5s default suits a looping bounce, not a button press.
animation-fill-mode. Add forwards to the shorthand to
hold the final frame. It is also worth wrapping any looping animation in a
@media (prefers-reduced-motion: reduce) query that turns it off.Frequently asked questions
Why does my CSS animation reset at the end?
Without animation-fill-mode the element reverts to its unanimated style once the last iteration finishes. Use forwards to keep the 100% frame, or backwards to apply the 0% frame during any delay.
What is the difference between animation and transition?
A transition needs a state change to trigger it and runs one way between two values. An animation runs on its own from the moment it is applied, can have as many intermediate keyframes as you like, and can repeat.
How do I make an element spin forever?
Keyframe from rotate(0deg) to rotate(360deg), then animate it with linear timing and infinite iterations. Any easing other than linear will make each revolution stutter at the seam.