A CSS animation generator with a real keyframe timeline
This CSS animation generator builds @keyframes animations the way motion designers think about them: as a timeline. Click the track to add a keyframe at any percentage, drag the diamonds to retime them, and give each keyframe transform, opacity, background colour or filter values. The tool merges identical keyframes (0%, 100% { … }) and writes the matching animation shorthand.
Easing gets its own editor. Pick a CSS keyword or a named curve such as “Overshoot”, drag the two handles of the cubic-bezier() graph, or switch to steps() for frame-by-frame motion. You can also give each keyframe its own easing to the next one, which is how a convincing bounce is made.
The preview runs the generated keyframes as a genuine CSS animation, so you can pause it, slow it to 0.25×, and scrub to any moment to inspect it. A prefers-reduced-motion fallback is included by default. Nothing leaves your browser.
How to use the CSS Animation Generator
- Choose a preset such as Bounce, Pulse, Shake or Typing caret, or start from any of them and change it.
- Click the keyframe track to add a keyframe (its values are interpolated from its neighbours), drag diamonds to move them, and tick the properties to animate: Transform, Opacity, Background colour or Filter.
- Select a keyframe and set its values and, optionally, its easing to the next keyframe.
- Under “Animation”, set the name, selector, duration, delay, repeat count, direction, fill mode and play state; under “Timing function”, pick or drag an easing curve, or use steps().
- Use Play, Pause, Restart, Speed and the scrub slider to check the motion, then press “Copy CSS”.
CSS Animation Generator features
Visual keyframe timeline
Add, drag and delete keyframes on a 0–100% track; a playhead shows exactly where the running animation is.
Cubic-bezier and steps() editor
Drag handles on the curve, type exact values, or choose steps with end, start, jump-none or jump-both.
Per-keyframe easing
Each keyframe can set its own animation-timing-function, as the Bounce preset does.
Scrub and slow motion
Inspect any frame with the scrub slider or run the preview at half or quarter speed.
Clean output
Default values are left out of the shorthand, identical keyframes are merged, and a longhand option is available.
Accessible by default
The reduced-motion media query is included unless you turn it off, and the preview itself starts paused when your device asks for reduced motion.
Worked example: the Bounce preset
Bounce writes animation: bounce 1s ease infinite; with three keyframes. At 0%, 100% the box is at translateY(0); at 50% it is at translateY(-40px). Each keyframe also sets animation-timing-function: cubic-bezier(0, 0, 0.2, 1) on the way up, so the box slows as it rises, and cubic-bezier(0.8, 0, 1, 1) from 50%, so it speeds up as it falls – the way gravity behaves.
Drag the scrub slider to the middle: the box sits exactly 40px up, because a keyframe’s value is always reached at its own percentage, whatever the easing. At 25% it is about 34px up rather than 20px, because the decelerating curve has already covered about 84% of that leg in the first half of its time.
The animation shorthand, value by value
| Longhand | Example | What it does |
|---|---|---|
| animation-name | bounce | Which @keyframes rule to run |
| animation-duration | 1s | Length of one cycle (the first time value) |
| animation-timing-function | ease-out | Speed curve between keyframes |
| animation-delay | 0.2s | Wait before starting (the second time value; negative starts part-way) |
| animation-iteration-count | 3, infinite | How many cycles |
| animation-direction | alternate | Play backwards on every other cycle |
| animation-fill-mode | both | Keep the first keyframe during the delay and the last one after the end |
| animation-play-state | paused | Freeze it, for example until hover |
Why the reduced-motion fallback is on by default
For people with vestibular disorders, large or constant movement – sliding panels, spinning loaders, zooming hero images – can cause dizziness, nausea or headaches. Operating systems therefore let users ask for less motion, and browsers expose that choice as the prefers-reduced-motion: reduce media query. WCAG 2.2 success criterion 2.3.3 (Animation from Interactions) asks that motion triggered by interaction can be turned off, and 2.2.2 (Pause, Stop, Hide) covers anything that moves for more than five seconds.
The generated block sets animation: none, which shows the element in its normal, un-animated state. If an animation carries meaning – a loading spinner, say – replace it with a gentler one, such as a slow opacity change, inside the same media query.
Performance tips
- Animate
transformandopacitywhere possible: browsers can usually run them on the compositor without recalculating layout. Colour and filter changes cost a repaint each frame. - Avoid animating
width,height,topormargin; use translate and scale instead – the CSS Transform Generator helps you find the right values. - Keep entrance animations short (roughly 150–500ms) so the interface still feels fast.
- Pair motion with other effects from the Box Shadow Generator or Gradient Generator, build the layout with the CSS Flexbox Generator, and shrink the final file with the CSS Minifier.
CSS Animation Generator FAQ
How do I make a CSS animation loop forever?
Set the iteration count to infinite: animation: pulse 1.5s ease-in-out infinite;. In this CSS animation generator, tick “infinite” next to Repeat.
What is the difference between a transition and an animation?
A transition animates between two states when a property changes, for example on hover. An animation runs @keyframes with any number of steps, can start on its own, loop and alternate.
Why does my element jump back after the animation ends?
By default the element returns to its own styles when the animation finishes. Use animation-fill-mode: forwards (or both) to keep the last keyframe.
What does cubic-bezier() mean?
It defines the speed curve with two control points (x1, y1) and (x2, y2); x is time and y is progress. The keywords are shortcuts: ease-in-out is cubic-bezier(0.42, 0, 0.58, 1).
How do I make a blinking cursor in CSS?
Load the Typing caret preset: opacity goes 1 → 0 → 1 with step-end timing, so it switches instantly instead of fading. Combine it with a steps() width animation for a typewriter effect.
Can I pause a CSS animation on hover?
Yes: add .box:hover { animation-play-state: paused; }. You can also start it paused with the Play state option and run it on hover instead.
Do CSS animations work in all browsers?
Yes. Unprefixed @keyframes and animation work in all current browsers; the -webkit- prefix is only needed for very old Safari and Android versions.