CSS Keyframes Generator

Generate CSS keyframe animations with presets and live preview. Free online tool with copy-ready code. No signup, browser-based.

Preparing private browser tool…

Your file will stay on this device.

How a keyframes rule defines an animation

An @keyframes rule is a named list of states expressed as percentages of the animation's duration. The keywords from and to are aliases for 0% and 100%. Between any two declared stops the browser interpolates every animatable property it finds, so @keyframes kf-fade-in { from { opacity: 0; } to { opacity: 1; } } describes a fade without saying anything about how long it takes or how many times it runs.

Timing is supplied separately by the animation properties on the element. The generated CSS pairs the rule with a block like .element { animation-name: kf-fade-in; animation-duration: 1s; animation-delay: 0s; animation-iteration-count: infinite; animation-timing-function: ease; animation-direction: normal; animation-fill-mode: both; }. That separation is the point of the design: one keyframes rule can drive many elements at different speeds.

A stop can list several percentages at once, which is how a cycle that returns to its starting point is written. The bounce preset uses 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-30px); }, declaring the same state at both ends so the element lands where it started.

What each animation property controls

Duration is the length of one iteration and delay is how long the browser waits before the first one starts. A negative delay is legal and useful: animation-delay: -0.5s on a two second animation starts it already half a second in, which is the standard way to desynchronise several copies of the same looping animation without writing extra keyframes.

The timing function shapes progress within each iteration. linear moves at a constant rate, ease and its variants accelerate or decelerate, and a custom curve such as cubic-bezier(0.68, -0.55, 0.27, 1.55) deliberately overshoots because its control points fall outside the 0 to 1 range, producing the anticipation and follow-through that reads as springy. The timing function applies per iteration, not across the whole animation.

Direction decides whether each iteration plays forwards or backwards. alternate makes even-numbered iterations run in reverse, which turns a one-way keyframes rule into a smooth back-and-forth loop and is usually preferable to writing a 0, 50, 100 cycle by hand. reverse plays every iteration backwards, and alternate-reverse starts backwards and alternates from there.

Fill mode, the property that causes the most confusion

Outside of its active period an animation normally has no effect at all: before the delay elapses and after the final iteration ends, the element shows its ordinary computed styles. That is why a fade-in with a delay flashes at full opacity before it starts, and why an element animated to opacity: 0 snaps back to visible at the end.

animation-fill-mode fixes both. The value backwards applies the first keyframe's styles during the delay, so the element sits at opacity: 0 while it waits. forwards keeps the last keyframe's styles after the animation finishes, so an element that animates out stays out. both does each, which is why this tool defaults to it.

Fill mode interacts with iteration count in a way worth remembering: with animation-iteration-count: infinite the animation never ends, so forwards has nothing to apply and the setting is effectively inert. It matters for finite animations, particularly one-shot entrances and exits.

Choosing properties that animate cheaply

Browsers render in stages: layout computes geometry, paint fills pixels, and compositing assembles layers on the GPU. Animating a property that changes geometry, such as width, height, top, left or margin, forces layout on every frame for that element and often its siblings. Animating background-color or box-shadow skips layout but still forces a repaint.

transform and opacity are the exceptions. Both can usually be handled entirely by the compositor, so the browser can run them on a separate thread at display refresh rate without touching layout or paint. Every preset in this tool is built on those two properties for exactly that reason: slide-up uses translateY rather than top, zoom-in uses scale rather than width, and shake uses translateX rather than left.

For accessibility, wrap non-essential motion in @media (prefers-reduced-motion: reduce) and either shorten it drastically or replace it with a simple opacity change. Vestibular disorders make large sliding, zooming and rotating movements genuinely uncomfortable, and the media query is the standard signal a user gives to say so.

Frequently asked questions

Why does my element flash before the animation starts?
During the delay the animation has no effect, so the element renders with its normal styles. Set animation-fill-mode to backwards or both so the first keyframe applies while the delay runs, which holds the starting state until the animation begins.
Why does my element snap back after the animation ends?
For the same reason, at the other end. Once the last iteration completes the animation stops applying styles. Use animation-fill-mode: forwards or both to keep the final keyframe in effect after the animation finishes.
How do I restart an animation from the beginning?
Removing and reapplying the class in the same frame does nothing, because the browser never sees an intermediate state. The reliable options are forcing a reflow between the two changes, or replacing the element so a fresh one starts clean, which is what the replay button in this tool does with a changing React key.
What is the difference between a transition and an animation?
A transition interpolates between two states and needs something to change it, such as a hover or a class toggle. An animation runs from a named keyframes rule on its own, can define many intermediate stops, and can loop. Use a transition for state changes and an animation for autonomous or multi-stage motion.
Why should I animate transform instead of top or left?
Changing top or left triggers layout on every frame, which is expensive and can drop frames on lower-powered devices. transform and opacity can usually be composited on the GPU without layout or paint, so they stay smooth under load.
Do I need vendor prefixes for keyframes?
Not for current browsers. The unprefixed @keyframes and animation properties have been supported for many years. Only add -webkit- prefixes if you are specifically targeting very old WebKit builds, and let a build-time tool such as Autoprefixer add them rather than writing them by hand.