CSS animation generator

Pick a starting animation, change its keyframes and timing, and watch it play. Then copy the @keyframes and the animation line — plain CSS, no JavaScript library.

Keyframes
Timing
Code
@keyframes fade-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

.fade-in {
  animation: fade-in 0.6s ease-out both;
}

@media (prefers-reduced-motion: reduce) {
  .fade-in {
    animation: none;
  }
}

How a CSS animation works

A CSS animation has two parts. The @keyframes block lists the stops — what the element looks like at 0%, at 100% and anywhere in between. The animation line on a class says which keyframes to play and how:

The tool animates opacity and transform only. Those are the two properties a browser can animate without working out the page layout again on every frame, so they stay smooth on phones. For colours, sizes or SVG paths, write the extra properties into the keyframes by hand.

Reduced motion

Some people turn on "reduce motion" in their phone or computer settings because movement on screen makes them dizzy or sick. With Add a reduced-motion rule ticked, the CSS includes a @media (prefers-reduced-motion: reduce) block that switches the animation off for them, and the Tailwind version adds motion-reduce:animate-none. The element then just shows its normal style. The preview on this page also starts paused if your device asks for less motion.

Using it

CSS — paste the code into your stylesheet and add the class (the animation name) to an element. It plays when the element appears; to play it again, remove the class and add it back. Tailwind — for Tailwind CSS v4: put the @theme block in your main CSS file after @import "tailwindcss";, then use the animate-… class. To animate a whole background, try the mesh gradient generator; for a hover effect on a button, the CSS button generator.

How we test it

221 animations — every preset, a few edge cases and 201 random ones with 2 to 10 keyframes and every timing function, direction and fill mode — are checked in Chrome 156. The CSS you copy is pasted in as it is, the animation is stopped at 3,190 moments (during the delay, inside each loop, after the end), and the opacity and transform Chrome works out must equal our own separate calculation of the CSS timing rules. The animation line must give Chrome exactly the same duration, timing, delay, count, direction and fill as the settings. The Tailwind version is compiled by the real Tailwind CSS 4.3.3 and must move the same way, and with reduced motion switched on both versions must stop. Deliberately broken versions — the wrong easing, keyframe percentages swapped, a missing px, the delay written before the duration, milliseconds written as seconds, a Tailwind theme without its keyframes — must each be caught. One thing the tests found: steps(1, jump-none) is not valid CSS (it needs 2 steps or more), so the tool will not write it.

Questions

Why does my element jump back when the animation ends?

That is the default fill mode, none. Set fill mode to forwards or both to keep the last frame.

How do I start the animation on scroll or on click?

CSS starts it when the class is added. Add the class with a little JavaScript when the element scrolls into view (an IntersectionObserver) or on click. This tool writes the animation, not the trigger.

Can I give each keyframe its own easing?

CSS allows animation-timing-function inside a keyframe. This tool uses one timing function for every step to keep the code short; add a per-keyframe one by hand if you need it.

Can I use the code in commercial work?

Yes. It is generated in your browser from the numbers you choose; there is nothing to credit and no licence attached.