Skip to main content

CSS Animation Generator

Create CSS keyframe animations with presets and visual preview. Doubles as an animate-CSS generator and keyframe maker.

Reviewed by · Last reviewed

1s
0s
CSS
@keyframes bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-30px); }
}

animation: bounce 1s ease 0s infinite normal none;

Building an Animation

  1. Select a preset - bounce, fade, slide, spin, pulse, shake, flip, zoom - from the preset grid. Each maps to a canonical @keyframes rule.
  2. Adjust timing: duration controls how long one iteration takes, delay postpones the start, iteration count sets how many times it plays (or infinite), and direction controls forward/reverse/alternate playback.
  3. Choose a timing function - linear, ease, ease-in, ease-out, ease-in-out, or a custom cubic-bezier() curve. This is the single biggest lever for how the animation "feels".
  4. Set fill-mode to decide what styles apply before the animation starts and after it ends - forwards locks in the final keyframe, which is what most real-world UI animations need.
  5. Watch the live preview. The preview element runs your animation on repeat so you can judge easing, duration, and feel before copying.
  6. Copy CSS. Output includes both the @keyframes rule and the animation shorthand ready to paste into your stylesheet.

What the animation engine actually does

CSS Animations are defined in CSS Animations Module Level 1, which introduced the @keyframes at-rule and the animation-* property family. When an element has an animation applied, the browser\'s style engine samples the keyframe values at each frame based on the elapsed time and the timing function, interpolating intermediate values per animatable property. The result is pushed through the normal paint/composite pipeline - except for properties that are compositor-friendly (transform and opacity), which skip paint entirely and run on the GPU.

This compositor distinction is the most important performance concept in CSS animations. Animating transform: translate3d and opacity can run at 60fps on any device because the main thread isn\'t involved after the keyframes are committed. Animating width, height, top, margin, or background-color forces the browser to re-run layout or paint every frame, which easily drops to 30fps on mobile. Chrome\'s "Performance" tab will flag "Forced reflow" and "Paint" events if you animate the wrong properties. The will-change: transform hint pre-promotes an element to its own compositor layer, eliminating the first-frame cost but consuming GPU memory - use it only on elements that will actually animate soon.

Cases where animation is the right call

  • Loading spinners using @keyframes spin with transform: rotate(360deg) and animation: spin 1s linear infinite.
  • Entrance transitions when a modal opens or a toast appears - fade plus slide gives the illusion of depth.
  • Attention-getting pulses on unread notification badges (sparingly).
  • Skeleton shimmer loaders animating background-position on a gradient.
  • Microinteractions like button press feedback, heart-icon bounces, cart-add flies.
  • Hero background effects - slow hue-rotate or gradient position shifts for ambient motion.

Pitfalls that bite in production

  • Respect prefers-reduced-motion. Users with vestibular disorders can experience nausea from parallax, zoom, and shake animations. Wrap decorative animations in @media (prefers-reduced-motion: no-preference) so users who\'ve opted out of motion never see them.
  • Animating layout properties kills frame rate. Animate transform and opacity, not width, height, top, left, or padding. For a "sliding drawer", use transform: translateX(-100%) to translateX(0) instead of changing left.
  • Animation chains get hard to debug. Multiple animation-delay values stacked on siblings look fine at first but become unmaintainable. The modern alternative is the Web Animations API (WAAPI) in JavaScript, or CSS scroll-driven animations (animation-timeline: scroll()) for chaining.
  • animation-fill-mode: forwards is usually required for entrance animations - otherwise the element snaps back to its pre-animation state after the final keyframe.
  • Infinite animations keep the main thread active even when offscreen. Pause them with animation-play-state: paused when the element isn\'t visible (e.g. via IntersectionObserver) to save battery on mobile.
  • cubic-bezier() values outside 0-1 on y-axis can overshoot, which is great for bounce effects but breaks properties that can\'t go negative (like opacity). The preview catches these visually.

Spec background and related standards

CSS Animations Module Level 1 was originally a WebKit proposal in 2009 and became a W3C Working Draft in 2013. The @keyframes at-rule and the animation shorthand are both defined there. Level 2 added scroll-driven animations - animation-timeline: scroll() and animation-timeline: view() - shipping in Chrome 115+. The related CSS Transitions Module Level 1 handles implicit state-change animations and is simpler when you only need two keyframes. The Web Animations API (WAAPI) provides the same primitives with procedural JS control. For timing functions, CSS supports Level 4\'s linear() multi-stop function and steps() for sprite-sheet animations. Browser support per caniuse.com/css-animation is universal for Level 1; scroll-driven animations need fallbacks.

CSS animation vs the alternatives

CSS animations are the right tool for declarative, fire-and-forget visual effects - loaders, entrance/exit transitions, hover accents. They are GPU-friendly when done right, they compose with design tokens via CSS variables, and they don\'t require any JavaScript. Where they lose: interactive animations that react to user input mid-flight, complex sequencing, physics-based motion (springs, inertia). For those, the Web Animations API or a library like Framer Motion or GSAP gives you imperative control. Compared to <img src="loader.gif">, CSS animations are crisper, themeable, and weigh almost nothing. Compared to Lottie or SVG SMIL, CSS is faster to author but less expressive for complex character animation. Rule of thumb: if a designer can sketch the animation in four keyframes and it plays the same way every time, use CSS. If it needs to respond or synchronize, reach for JavaScript.

Frequently Asked Questions

Which CSS properties are cheap to animate?

Only <code>transform</code> and <code>opacity</code> can be animated on the compositor thread without triggering paint or layout. Everything else - <code>width</code>, <code>height</code>, <code>margin</code>, <code>top</code>, <code>left</code>, <code>background-color</code>, <code>color</code>, <code>font-size</code>, <code>filter</code> - forces a layout or paint pass every frame, which can push frame rates below 30fps on mobile. For a slide animation, use <code>transform: translateX()</code> not <code>left</code>; for a fade, use <code>opacity</code> not <code>visibility</code>; for a scale, use <code>transform: scale()</code> not <code>width</code> and <code>height</code>.

What is the difference between animation and transition?

A <code>transition</code> fires when a property changes value (typically on hover, focus, or class toggle) and interpolates between the old and new values. An <code>animation</code> uses <code>@keyframes</code> to describe a full timeline of styles, runs on a schedule independent of state changes, and can loop, reverse, or alternate. Transitions are better for state-driven micro-effects (button hover lightens); animations are better for standalone effects (spinner, pulsating notification). They can coexist on the same element.

How do I stop an animation mid-flight?

Set <code>animation-play-state: paused</code> to freeze the animation at the current frame without resetting it - the next <code>running</code> value resumes from where it stopped. To fully cancel, remove the animation from the <code>animation-name</code> list (or remove the class that applies it). In JavaScript, the Web Animations API gives more control: <code>element.getAnimations()[0].pause()</code>, <code>cancel()</code>, <code>finish()</code>, or <code>reverse()</code> are all standard.

Why do users sometimes see my animation flash back to the start?

Because <code>animation-fill-mode</code> defaults to <code>none</code>, which means after the last keyframe plays, the element snaps back to its pre-animation style. For entrance animations (fade in, slide in) you almost always want <code>animation-fill-mode: forwards</code> to keep the final keyframe's values applied. For cyclical animations (spinners, pulses), <code>none</code> is fine because they loop forever and never finish.

Does this generator send my animation settings anywhere?

No. The preset, timing values, and all other controls live in component state in your browser. The <code>@keyframes</code> rule is injected into a <code>&lt;style&gt;</code> block local to the preview, and the preview element's animation property is set via inline styles. There is no server round-trip for preview rendering.

How should I handle users who prefer reduced motion?

Wrap animations in a media query: <code>@media (prefers-reduced-motion: no-preference) { .element { animation: ...; } }</code>. This respects the OS-level "Reduce motion" setting and prevents motion-sensitive users from experiencing animations they've opted out of. For essential animations provide a simpler static fallback rather than disabling them entirely.

What is the best duration for a UI animation?

Research from Google's Material Design and Apple's Human Interface Guidelines converges on 150-300ms for most UI transitions - long enough to read as a transition, short enough not to feel sluggish. Larger elements can go up to 400ms; small hover feedback should stay under 150ms. For decorative animations (hero pulses, background gradients), 1-3 seconds reads as ambient rather than interactive.

How do I debug a CSS animation that looks wrong?

Chrome DevTools has a dedicated "Animations" panel (more tools > Animations) that captures every animation on the page, lets you scrub through keyframes, adjust timing functions with a visual curve editor, and slow down all animations by 10x or 25x to see subtle details. Firefox's "Animations" panel has similar features.

What's the difference between ease-in, ease-out, and ease-in-out?

<code>ease-in</code> starts slow and accelerates - good for elements leaving the screen. <code>ease-out</code> starts fast and decelerates - good for elements arriving, landing gently. <code>ease-in-out</code> combines both, which produces the most "natural" feel for two-state transitions. <code>linear</code> moves at constant speed and should be reserved for rotation and other continuous motion - linear easing on translate or scale looks robotic.

Is this the same as an Animate CSS generator or a keyframe generator?

Yes. "Animate css generator", "css animate", "keyframe animation generator" and "css keyframe generator" all point at a tool that produces a <code>@keyframes</code> block plus a matching <code>animation</code> shorthand. This page writes both. If you have used the popular animate.css library, the built-in bounce/fade/slide/spin presets here will feel familiar - they map to the same canonical keyframes but ship as plain CSS you can copy into any project without the library dependency.

More CSS & Design