Free · Fast · Privacy-first

CSS Bounce Animation

A bounce animation overshoots its target position, reverses direction, and settles into place, mimicking the physics of an elastic collision between a soft object and a rigid surface.

Adjustable overshoot amount and number of bounces

🔒

Choice between cubic-bezier and multi-stop keyframe approach

Preview distinguishes subtle spring from cartoon bounce

Generates complete, copy-ready CSS

Cost
Free forever
Sign-up
Not required
Processing
In your browser
Privacy
Files stay local
FreeNo signupWhite-label

Add this Animation Builder to your website

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.

  • Files stay 100% in the visitor's browser
  • Responsive — adapts to any container width
  • Free forever, no API key needed

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.

What Makes a Bounce Animation and the Two CSS Approaches to Building One

A bounce animation works because the element travels past its target position, reverses direction, and settles at the target after one or more oscillations. This mimics the physics of a ball, a spring, or any elastic material that overshoots equilibrium before coming to rest under the action of damping. The key parameters are the overshoot distance (how far past the target the element travels in the first oscillation), the number of oscillations (one for a clean spring effect, three or more for a repeated cartoon-style bounce), and the timing decay between oscillations (how quickly energy is lost with each successive bounce, which controls whether the bounce feels heavy and damped or light and elastic). Getting these three parameters balanced creates an animation that feels physically believable rather than arbitrary, and the calibration changes substantially based on the size and visual weight of the animated element.

CSS provides two approaches for building bounce animations. The first uses a custom cubic-bezier timing function with control point Y values above 1.0, which causes the animation to overshoot the target value beyond the normal 0 to 1 range that standard easing functions operate within. A cubic-bezier like cubic-bezier(0.34, 1.56, 0.64, 1) produces a clean single-bounce spring effect for scale and translate properties without requiring any intermediate keyframe stops, making it the simplest implementation when a single overshoot and settle is all you need. The second approach uses a multi-stop @keyframes rule that manually defines each bounce position: the element reaches 110% of its target at 60%, drops back to 95% at 80%, overshoots smaller at 102% at 90%, and arrives at 100% at the final stop. The keyframe approach gives finer control over the number and shape of each oscillation but requires more stops to look natural.

Bounce animation use cases span three distinct categories with different parameter requirements. Call-to-action buttons use a subtle scale bounce (scale 1 to 1.05 to 0.97 to 1) to signal interactivity or to confirm a click with a small physical response that mimics the press of a real button. Empty-state illustrations use a vertical bounce on an icon or illustration to give the page life without overwhelming the user with motion, typically running indefinitely at a slow tempo. Error feedback uses a horizontal shake (alternating translateX between negative and positive offsets) that is technically a damped bounce, communicating that the input was rejected through a motion pattern that humans associate with the head-shake gesture. Each use case requires a different overshoot magnitude and duration, which is why previewing before copying is more efficient than adjusting values blindly in code.

Transform-origin is the parameter that most often distinguishes a polished bounce from one that looks technically correct but feels wrong. By default, transform-origin is set to the center of the element, so a scale bounce expands and contracts symmetrically from the center point. This is correct for most badges, buttons, and icons. But for elements that should feel anchored to a surface (a tooltip pointing down at its target, an illustration standing on a baseline, a notification badge attached to the top-right of a parent), setting transform-origin to the appropriate edge or corner makes the bounce feel like it has weight and ground rather than floating in space. A transform-origin: bottom center on an icon makes the scale bounce look like inflation from the floor, which reads as a much more physical motion than a center-anchored expansion.

How to use this tool

💡

Set the overshoot amount and choose between a single-bounce spring and a multi-bounce effect. Adjust duration to match the weight of the element. Preview the result and copy the generated CSS.

How It Works

Step-by-step guide to css bounce animation:

  1. 1

    Choose the bounce type

    Select spring bounce for a single overshoot and settle effect produced with a cubic-bezier timing function, suitable for button feedback and badge pops where one elastic motion communicates the response. Select multi-bounce for several oscillations using a multi-stop @keyframes rule, suitable for empty-state illustrations and playful entrances where the repeated motion adds character. The choice affects how many keyframe stops the generator produces and how the easing curve behaves between them.

  2. 2

    Set overshoot magnitude

    Adjust the overshoot amount based on the role and size of the element. A 5 percent overshoot looks subtle and is appropriate for buttons and other professional UI elements where the bounce should be barely noticeable. A 15 to 20 percent overshoot looks energetic and is appropriate for illustrations, mascots, and onboarding components where playfulness is intended. Above 25 percent the bounce starts to look cartoonish, which is correct only for games and children's applications and almost never for standard business or consumer UI.

  3. 3

    Set duration for element weight

    Set the animation duration relative to the implied physical weight of the element being animated. A light button click warrants 300 to 400 milliseconds, where the short duration matches the brief tactile sensation of pressing a real button. A heavier illustration entrance warrants 500 to 700 milliseconds, where the longer duration matches the slower deceleration expected from a larger physical object. Match duration to perceived mass for a result that feels grounded in physics rather than arbitrary.

  4. 4

    Copy and apply the CSS

    Click Copy Code to copy the @keyframes block and animation property to your clipboard. Paste both into your stylesheet at the appropriate location and apply the animation class to the target element. Verify the bounce in your real application context against the preview, since the perceived bounce magnitude depends on the element's actual size and surrounding layout, which may differ from the preview element. Adjust overshoot if needed to match the intended feel at the production element size.

Real-world examples

Common situations where this approach makes a real difference:

CTA button click confirmation

An e-commerce site applies a scale bounce on the Add to Cart button click using transform: scale(1) to scale(1.06) to scale(0.97) to scale(1) across four @keyframes stops at 0, 40, 70, and 100 percent. The animation runs once at 300 milliseconds when the button is clicked, providing haptic-like visual feedback that the action was registered before the network request completes. The subtle overshoot prevents the click from feeling flat without crossing into cartoonish territory inappropriate for a checkout flow. The same animation class is reused on every primary CTA in the application for a consistent click response across the product surface.

Empty state illustration bounce

A project management application's empty state shows an illustration that continuously bounces vertically using a translateY(0) to translateY(-12px) alternate animation set to infinite iteration. The 1.2 second duration makes the bounce feel slow and gentle, matching the calm tone of an empty state rather than an urgent alert that demands immediate attention. The animation pauses entirely when the prefers-reduced-motion media query is active, replacing the bouncing illustration with a static version for motion-sensitive users. The illustration becomes a friendly focal point that draws the eye to the Create Project CTA without feeling demanding.

Form validation error shake

A sign-in form applies a shake animation to the input group when the user submits an incorrect password. The @keyframes rule defines six stops with alternating translateX values of -8 and 8 pixels, settling back to 0 at the 100 percent stop. The 500 millisecond single-play animation runs when an error class is added to the form container by the validation handler. The class is removed from the form after the animationend event fires, which allows the shake to be triggered again immediately on the next failed login attempt without requiring a page refresh or a debounce delay. The shake is paired with a red border color change for redundancy.

Notification badge pop

A messaging application adds a scale bounce to notification count badges every time a new message arrives in the inbox. The badge scales from 1.0 to 1.4 then to 0.9 then to 1.0 over 400 milliseconds using a spring cubic-bezier easing function. The large 40 percent overshoot is appropriate specifically for badge elements, which are small in absolute size so even aggressive scale changes remain proportional and do not create visual collisions with adjacent content. The pop animation immediately signals new activity without requiring any color change, which is important because badge color is reserved for severity levels.

When to use this guide

Use this for call-to-action buttons, empty-state illustrations, error feedback, and any element that should feel lively or draw attention through physical energy rather than just motion.

Pro tips

Get better results with these expert suggestions:

1

Match overshoot to element size

Large elements like panels, hero cards, and full-page images need a smaller overshoot percentage than small elements like icons and badges to feel equivalent in perceived energy. A 5 percent scale overshoot on a 400 pixel card moves the edges by 20 pixels in absolute terms, which is substantial. The same 5 percent on a 20 pixel icon moves only 1 pixel, which is barely perceptible. Scale your overshoot percentage inversely with element size to keep the perceived physical energy of the bounce consistent across different components in the same design system.

2

Use transform-origin to control bounce direction

Set transform-origin on the element before applying a scale bounce to control which edge or corner acts as the anchor point during the scale animation. transform-origin: bottom center creates a bounce that expands upward like a ball inflating from the ground, which is the right anchor for standing illustrations and characters. transform-origin: center produces a symmetric pop from all sides, which is right for badges and floating elements. transform-origin: top right anchors the bounce to a corner, useful for tooltips and dropdown menus that attach to a parent. The generator sets transform-origin: center by default.

3

For multi-bounce effects, use fewer stops than you think

A three-bounce effect only needs five keyframe stops at 0, 30, 60, 80, and 100 percent. Adding more stops produces diminishing returns in realism and makes the keyframe block harder to adjust later when timing needs to change. Start with five stops and refine the position values to nail the bounce shape before considering additional stops. The timing intervals between stops (30, then 30, then 20, then 20) create the natural decay in bounce amplitude that mimics real physical damping, where each successive bounce occupies less time and travels less distance than the one before it.

4

Avoid bounce animations on elements above 500px

Bounce animations on large elements are visually aggressive and can cause motion sickness or general discomfort for sensitive users even when prefers-reduced-motion is not set. The overshoot distance scales with the element size, so a 5 percent overshoot on an 800 pixel hero image moves 40 pixels of content, which dominates the visual field. Reserve bounce animations for elements under 200 pixels where the overshoot distance remains small in absolute terms. For large elements that need physical energy, use a subtle ease-out spring via a cubic-bezier overshoot rather than an explicit multi-bounce @keyframes that amplifies the motion.

FAQ

Frequently asked questions

A spring animation overshoots once and settles, like a spring being compressed and released, where the energy is dissipated within a single oscillation cycle. A bounce animation overshoots and oscillates multiple times with decreasing amplitude, like a ball dropped on the floor where each successive bounce loses energy until the ball comes to rest. In CSS, springs are implemented with a custom cubic-bezier that overshoots the 1.0 Y value to produce a single overshoot peak followed by a settle, while multi-bounce effects require explicit percentage stops in a @keyframes rule that define each bounce position. For UI components, spring behavior is more common because it feels controlled and professional, while multi-bounce is reserved for playful, game-like interfaces and onboarding moments.
Yes. Set animation-iteration-count: infinite and adjust the @keyframes to have matching start and end states. A continuously bouncing element works well for empty-state illustrations, attention-grabbing loaders, and ambient indicators that should signal activity without requiring user interaction. Use a symmetrical keyframe where the element returns to the starting state at 100 percent, ensuring smooth looping without a visible jump between iterations. Alternatively, set animation-direction: alternate to make the animation play forward then backward on successive iterations, which creates a more natural oscillation without requiring a return keyframe and halves the amount of keyframe code needed for the same effect.
Use a cubic-bezier where the Y values of the control points exceed 1.0, which causes the animated value to overshoot its target beyond the normal 0 to 1 interpolation range. For example, cubic-bezier(0.34, 1.56, 0.64, 1) produces a clean spring overshoot at roughly 56 percent past the target before settling back to 100 percent. This approach only produces a single-bounce spring, not multiple oscillations, but the simplicity is its strength: you only need a simple from-to keyframe block, and the easing function handles the bounce shape automatically without any intermediate stops to maintain. This is the most common approach for button and card scale bounces in production design systems.
Cubic-bezier implementations are consistent across modern browsers for standard control points in the 0 to 1 Y range. For cubic-bezier control points outside the 0 to 1 Y range (used to produce overshoot effects beyond the natural interpolation), rendering can differ slightly between browsers because the specification allows implementation flexibility for out-of-range values. If a spring cubic-bezier looks correct in Chrome but wrong in Safari, switch to a multi-stop @keyframes approach that explicitly defines each bounce position as a percentage value. The @keyframes approach is fully deterministic across all browsers because the interpolation happens between fixed declared values rather than through an extrapolation of the easing curve.
Animate transform: scale() for scale bounces, not width and height. Animating width and height triggers layout recalculation on every animation frame, causing jank on complex pages with many DOM nodes and forcing surrounding elements to reflow continuously while the bounce plays. Using transform: scale() runs the animation entirely on the GPU compositor thread with zero layout cost, regardless of how many other elements are on the page. Set the element's transform-origin property to control the anchor point of the scale: transform-origin: center is the default and produces symmetric expansion, but transform-origin: bottom center creates a bounce-from-floor effect for standing characters, icons, or any element that should feel grounded.
Combine a slide-in with a bounce on arrival to produce a drop-and-settle entrance that feels like the element fell into place. Use translateY(-20px) at 0 percent, translateY(8px) at 65 percent (the overshoot below the target), translateY(-4px) at 80 percent (the small return up), and translateY(0) at 100 percent (the final resting position). Add opacity 0 at 0 percent and opacity 1 at 20 percent to hide the element during the initial drop position, which prevents the visual oddity of the card being visible above its target before the animation starts. The combination creates an entrance with two clear motion phases: arrival and settle, with the bounce at the arrival point acting as a landing signal.
For a button scale bounce, an overshoot of 5 to 8 percent above the target scale feels subtle and satisfying, similar to the small physical compression of pressing a real keyboard key or physical button. So if the base scale is 1.0, the peak scale should be 1.05 to 1.08. Above 10 percent overshoot starts to look playful and is appropriate for consumer-facing apps with a friendly tone. Above 15 percent the bounce reads as cartoonish, which is incorrect for most professional UI contexts but right for games or children's apps. Match the overshoot to the overall tone of the product: consumer apps tolerate more energetic motion; enterprise dashboards and financial tools expect very subtle responses. The key test is whether the bounce feels like physics or like a cartoon.
Yes. A horizontal shake implemented as alternating translateX values (from 0 to negative 8 pixels, to positive 8 pixels, to negative 6 pixels, to positive 6 pixels, back to 0) is a form of damped bounce animation that communicates rejection or error through a motion pattern that humans intuitively associate with the head-shake gesture. Keep the duration between 400 and 600 milliseconds and the iteration count at 1 so the shake plays once and stops. Avoid continuous looping for error feedback, as an endlessly shaking element becomes annoying rather than informative and can actually impair the user's ability to read the error message. Trigger the animation by adding and removing a CSS class after a failed form submission so it can be retriggered on subsequent failures.
Yes, and this is particularly important for bounce animations because the oscillating motion is more likely to trigger vestibular symptoms in motion-sensitive users than a simple fade or linear translate. Wrap the bounce animation declaration in a media query check: outside the @media (prefers-reduced-motion: reduce) query, define the bounce normally; inside it, set animation: none for the same element so the bounce is skipped entirely. The element appears immediately at its final state for users who have requested reduced motion in their OS accessibility settings. WCAG 2.1 guideline 2.3.3 requires this override for non-essential animations, and bounce effects are squarely in the non-essential category.
Define the bounce keyframes and animation property in a CSS class, then add that class to the element via JavaScript at the moment you want the bounce to play. For example, define .bounce-in with the animation declaration, then call element.classList.add('bounce-in') when the element should bounce. To retrigger the bounce on the same element later, remove and re-add the class inside a requestAnimationFrame callback so the browser registers the class change as a new animation start rather than ignoring it. This pattern lets you keep the bounce definition declaratively in CSS while triggering it imperatively from event handlers and state changes.

Related guides

More use-case guides for the same tool:

Ready to get started?

Open the full Animation Builder — free, no account needed, works on any device.

Open Animation Builder →

Free · No account needed · Works on any device