Stripe-style payment success animation in pure CSS
The animated checkmark, the elastic ring, the confetti — the full Stripe-style payment success animation in CSS. Free source, MP4 export.
If you've ever paid for anything online in the last five years, you have seen this animation: the ring closes, a checkmark draws, the whole thing settles with a single elastic overshoot, and you exhale. Stripe's checkout team got it right; everyone copied it; now it is the visual grammar of "your money moved."
There are two reasons to rebuild this in your own code instead of leaning on a Lottie file. First, it is small — under 80 lines of CSS. Second, you can render it to MP4 for a launch video, a help article, or an onboarding flow without touching After Effects.
What the animation actually does
Three timed beats, in this order:
- The ring traces (0.0 – 0.5s) — a circle stroke draws from the top, clockwise, all the way around. Eases in slow, eases out faster.
- The checkmark draws (0.4 – 0.7s) — overlapping with the ring's last 100ms, so the eye reads continuity, not sequence.
- The whole thing settles (0.7 – 0.95s) — a single elastic overshoot, ~6%, then back. This is the "exhale" beat.
Total runtime: under a second. Anything slower and it feels like a loading spinner instead of a confirmation.
The ring (technique)
A stroked SVG <circle> with stroke-dasharray set to the circumference and stroke-dashoffset animated to zero. The rotation trick: start the stroke from the top instead of the right with transform="rotate(-90)".
The checkmark (technique)
An SVG <path> with stroke-dasharray and stroke-dashoffset — same primitive as the ring, applied to a polyline. The path is just two line segments: down-and-right, then up-and-right.
The elastic settle (technique)
CSS transform: scale() with a custom easing curve. The cubic-bezier that gives that "snappy overshoot" without feeling cartoonish:
transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);The 1.56 second control point is what pushes past 1.0 before settling. Drop it to 1.2 for subtle, push to 1.8 for cartoony.
The full source
<div class="success">
<svg viewBox="0 0 100 100" class="ring">
<circle cx="50" cy="50" r="44"
fill="none" stroke="#1f8a5b" stroke-width="6"
stroke-linecap="round"
stroke-dasharray="277" stroke-dashoffset="277"
transform="rotate(-90 50 50)"/>
<path class="check"
d="M30 52 L46 66 L72 38"
fill="none" stroke="#1f8a5b" stroke-width="7"
stroke-linecap="round" stroke-linejoin="round"
stroke-dasharray="80" stroke-dashoffset="80"/>
</svg>
<div class="text">Payment received</div>
</div>Variants worth keeping
Every product needs a success animation, but the variant rarely matters as long as the timing rules are kept. Three useful skins:
- Green ring + check (above). Default. Reads as "money / commerce."
- Brand-color ring + check. Same shape, your accent color. Use for "sign-up complete," "form sent."
- Ring + check + 20-particle confetti burst. Reserve for celebratory states — first purchase, milestone hit.
Rendering to MP4 (for onboarding / launch videos)
The animation is pure CSS/SVG, so it lifts directly into the render pipeline. Two practical uses:
- Onboarding video — drop the success state into a 9:16 walkthrough, render once.
- Launch video — pair the animation with confetti particles and a tagline for a 4-second hero loop.
Set the loop duration to 1.2s with a 200ms hold at the end — gives the eye time to read the label before the next loop starts.
Why this still matters
Every checkout flow in 2026 still gets this wrong. The two most common failures: the animation runs too long (looks like buffering), or it has no settle beat (feels abrupt). Both are calibration issues, both are fixable in a single CSS file.
If you ship a payments product, an onboarding flow, or any transactional UI — copy this pattern, calibrate the timing, ship it once. Then render it to video for the help docs, the marketing site, and the in-app tour.
Cite this postBibTeX · APA · Markdown
@misc{okafor2026stripestyle,
author = {Marcus Okafor},
title = {Stripe-style payment success animation in pure CSS},
year = {2026},
url = {https://hyperframes.video/blog/payment-success-animation-css},
note = {HyperFrames blog}
}Marcus Okafor. (2026, May 6). Stripe-style payment success animation in pure CSS. HyperFrames. https://hyperframes.video/blog/payment-success-animation-css
[Stripe-style payment success animation in pure CSS](https://hyperframes.video/blog/payment-success-animation-css) — Marcus Okafor, 2026
Marcus leads design and motion at HyperFrames. Before that he shipped editorial motion for newsrooms and product launches. He thinks every easing curve has a personality.
How to animate your logo (without After Effects)
A logo reveal in pure CSS — spring overshoot, wordmark stagger, and a render straight to MP4. No timeline tool, no plugins.
Scroll-driven video: turning timelines into scroll positions
CSS scroll-driven animations finally went baseline in 2026. A practical tutorial on mapping video timelines to scroll positions, when to use scroll vs video, and the hybrid pattern we use on hyperframes.dev.
Motion graphics in 80 lines
A complete title sequence — bouncy text, parallax backdrop, signal-color accent, cinematic ease — written in 80 lines of plain HTML. No framework. No tooling beyond the browser.
Building with HyperFrames? Come hang out.
We're on GitHub, in Discord, and the playground is one click away. Bring weird ideas — we collect them.