The @keyframes rule is the core of every CSS animation, but building one with multiple stops, varied properties, and correct percentages by hand requires constant trial-and-error and a lot of editor-to-browser context switching.
Loading Animation Builder…
Add keyframe stops at any percentage from 0 to 100
Set multiple CSS properties per stop
Live preview updates as stops are added or modified
Outputs a named @keyframes block ready for any animation property
Drop the Animation Builder into any page — blog post, product docs, intranet, school portal — with a single line of HTML. Your visitors get the full tool, processed entirely in their browser. No backend, no uploads, no signup.
Embed code
<iframe
src="https://www.fixtools.io/css-tool/animation-builder?embed=1"
width="100%"
height="780"
frameborder="0"
style="border:0;border-radius:16px;max-width:900px;"
title="Animation Builder by FixTools"
loading="lazy"
allow="clipboard-write"
></iframe>Attribution-friendly: a small "Powered by FixTools" link appears in the embed footer.
A @keyframes rule consists of the keyword @keyframes followed by an animation name, then a block containing one or more keyframe selectors. Each selector is either the from keyword (equivalent to 0%), the to keyword (equivalent to 100%), or an explicit percentage between those endpoints. The properties declared inside each selector define what the element looks like at that point in the animation timeline, and the browser handles the rest by interpolating the property values smoothly between consecutive stops using the active easing function declared in the animation shorthand. A two-stop animation using from and to is the simplest case: the element transitions from one state to another over the full duration with a single easing curve shaping the entire motion. Most real-world animations need more stops because the kinds of motion that feel natural to human perception (a bounce that overshoots and settles, a shake that alternates direction, a progress fill that pauses partway through) cannot be expressed as a single straight interpolation between two endpoints. The keyframes generator lets you add as many stops as the animation needs while keeping the syntax correct and the preview accurate to what the browser will render.
Multiple keyframe stops let you describe complex motion paths that a two-stop animation cannot express in any number of cubic-bezier tweaks. A bounce animation might travel down to its target position at 60%, overshoot to -10px at 75%, recover to -5px at 85%, and settle at 0 at 100% so the eye reads the motion as something with weight and momentum. A shake animation alternates between translateX(-8px) and translateX(8px) across six stops spaced 10% apart to suggest a vibrating object or an emphatic form validation error. A progress indicator might hold at 30% opacity for the stops between 40% and 60% to create a visible pause mid-animation that emphasizes a specific moment in the sequence. Each additional stop adds a control point that shapes the overall motion, giving you fine-grained control over how the animation unfolds without ever leaving the declarative CSS layer or pulling in a JavaScript animation library. The generator exposes a stop list you can reorder, duplicate, or delete, which makes it easy to experiment with different rhythms (three stops, then five, then seven) and pick the one that reads best at the duration your design requires.
A common pitfall with @keyframes is how the browser handles properties that are not declared at every stop. If a property appears at 0% and 100% but not at 50%, the browser interpolates smoothly through 50% as expected. But if a property appears only at 50% and not at 0% or 100%, the browser interpolates from the element's computed style to the 50% value, then back to the computed style. This means the animation depends on the element's base styles, which can produce unexpected results if the base styles change later or differ across themes and breakpoints. Declaring the property explicitly at 0% and 100% makes the animation self-contained and predictable regardless of the surrounding CSS, and the generator follows this convention automatically when you add properties to intermediate stops without first defining them at the endpoints.
A well-built keyframes generator becomes a teaching tool as well as a productivity tool because every adjustment you make to the visual controls maps one-to-one onto a line of generated CSS you can read in the output panel. Beginners learning the animation specification can add a stop, toggle a property, and immediately see exactly which percentage selector and which property declaration the change produces, building an intuitive model of how the cascade between declarative timing and rendered motion actually works. Experienced engineers use the same tool to skip the typing and jump directly to the experimental loop, trying three different five-stop bounces in the time it would take to write one of them in a code editor. Either audience benefits from never having to debug a malformed @keyframes block, since the generator guarantees the output is syntactically valid CSS that the browser will parse correctly the moment you paste it into your stylesheet.
Click Add Stop to insert a keyframe at any percentage. Set the CSS properties for that stop, add more stops as needed, then preview the sequence. Copy the @keyframes block when the motion is correct.
Step-by-step guide to css keyframes generator:
Name the animation
Enter an animation name in the name field at the top of the controls panel. Choose a descriptive name like bounce-in, shake-error, or pulse-badge that reflects what the animation does rather than what properties it animates. The name you pick is what your CSS selectors will reference in their animation-name property, so a clear functional name pays off every time you read or refactor the stylesheet later.
Add keyframe stops
Click Add Stop and enter the percentage for each point in the timeline. Add the 0% stop first to define the starting state, then add intermediate stops at the percentages where the motion needs to change direction, hold a value, or hit a milestone, then finish with the 100% stop. The generator lets you reorder stops by dragging and delete any stop with a single click, so you can experiment with different rhythms before locking in the final sequence.
Set properties at each stop
For each stop, enter the CSS property and value pairs that describe the element at that point in the animation. Use transform for position, rotation, and scale changes, opacity for fade states, and color or background-color for color transitions. Declare the same set of properties at every stop (even when the value does not change) to make the animation self-contained and predictable regardless of the element's surrounding base styles.
Copy the generated code
Click Copy Code to copy the complete @keyframes block plus the matching animation shorthand declaration to your clipboard, then paste both into your CSS file. Place the @keyframes rule at the top level of your stylesheet (or inside a media query if it should only run at certain breakpoints) and attach the animation shorthand to the selector for the element you want to animate. The generated output is unprefixed standard CSS that works in every modern browser without any post-processing.
Common situations where this approach makes a real difference:
Multi-step notification shake
A developer builds a form validation error effect using six keyframe stops that alternate translateX between -8px and 8px at 10% intervals from 0% to 60%, then return to 0 at 100%. The shake runs once (iteration-count: 1) when an error class is added by the validation handler, then the class is removed after the animation finishes so the effect can be retriggered on the next failed submit. The generator handles the six-stop keyframe block in under a minute, which would take several minutes to write, debug, and visually verify manually, especially when fine-tuning the amplitude and timing to feel emphatic without crossing into annoying territory.
Progress bar with hold states
A UI engineer creates a fake progress bar that advances to 30% quickly, holds for two-thirds of the duration (using duplicate width values at the 30% and 70% stops), then advances to 100%. The generator places stops at 0%, 30%, 70%, and 100% with matching width values at the hold stops so the browser interpolates correctly between segments. The animation runs once with a 3-second duration, giving a convincing progress simulation for a backend process that the team has not yet wired up to a real streaming progress event. The pattern is easy to maintain because the hold percentages can be adjusted independently of the start and end values whenever the perceived pacing needs tweaking.
Logo reveal animation
A brand agency developer creates a 5-stop keyframe animation for a logo reveal: starts at opacity 0 and scale(0.8), eases to opacity 1 at 50%, scales to 1.05 at 70%, drops to 0.97 at 85%, and settles at scale(1) and opacity 1 at 100%. The slight overshoot and settle gives the logo a premium spring quality that pure ease-out interpolation cannot match, and pairing it with a 900ms duration on the hero section creates a memorable load-in moment that becomes part of the brand experience. The generator produces the exact transform values for each stop and writes the matching animation shorthand, leaving no ambiguity about timing during the developer handoff.
Staggered list item entrance
A React developer generates a slide-up-fade keyframe block with three stops: 0% at translateY(20px) opacity 0, 60% at translateY(-4px) opacity 1, and 100% at translateY(0) opacity 1. The 60% stop with a small upward overshoot adds a hint of bounce that makes the entrance feel responsive rather than mechanical. The same @keyframes block is applied to each list item with animation-delay values of 0s, 0.1s, 0.2s, and 0.3s to create the staggered cascade effect common in dashboard interfaces and email clients. Because the keyframe definition is shared, changing the motion later (say, increasing the upward overshoot from -4px to -6px) updates every list item in the application at once.
Use this when you need a multi-step CSS animation with more than two states, such as a bounce, a shake, or a progress sequence with pauses.
Get better results with these expert suggestions:
Declare the 0% stop explicitly for predictable behavior
Omitting the 0% stop means the animation starts from the element's computed style, which is fine until a parent component applies a conflicting style, a theme variant overrides the base values, or a developer refactoring the stylesheet six months from now changes the element's default transform without realizing an animation depends on it. Always declare the 0% stop with the starting values you intend, making the animation self-contained and resistant to styling changes elsewhere in the stylesheet. The handful of extra bytes pays for itself the first time a refactor would have silently broken the motion.
Use transform for all positional keyframes
Animating left, top, margin, padding, or width through keyframes triggers layout recalculation on every frame, which forces the browser off the compositor thread and can cause visible jank, particularly on lower-end mobile devices or when several elements animate simultaneously. Replace all positional changes with translateX() and translateY() in your keyframes, and replace size changes with scale() when the visual effect allows it. The visual result is nearly identical for entrance and exit motion, but the animation runs at the device's native refresh rate on the compositor thread, leaving the main JavaScript thread free for everything else the page needs to do.
Name keyframes by function, not by property
Name your @keyframes blocks after what the animation does (bounce-in, shake-error, pulse-badge, slide-up-fade) rather than what properties it animates (transform-scale, opacity-fade, translate-x-shake). Functional names remain meaningful when you refactor the keyframe values, are easier to search across a stylesheet of any size, and communicate intent to other developers (or your future self) who read the code months later without context. A name like bounce-in still describes the animation accurately if you later decide to swap the transform for a clip-path effect; a name like transform-scale becomes a lie the moment the implementation changes.
Test the animation at animation-duration: 3s while building
Set a very long duration (3 to 5 seconds) while designing the keyframe stops. This makes individual stops easy to distinguish visually and reveals whether intermediate states look correct in their own right or only work because they pass by quickly at the intended speed. Once the stops are right, reduce the duration to the intended value (typically 200 to 600 milliseconds for entrance and exit animations) and verify the motion still reads correctly. Building at full speed hides issues at intermediate stops that only become obvious when the animation runs slowly, and slow-building is one of the few habits that consistently separates production-quality motion from animation that feels off without anyone being able to say why.
More use-case guides for the same tool:
Open the full Animation Builder — free, no account needed, works on any device.
Open Animation Builder →Free · No account needed · Works on any device