Confetti, sparkles, and other particle tricks in pure CSS
Two hundred particles, gravity, rotation, and a single canvas. No library, no engine, no After Effects.
The most over-engineered animation in the modern web is confetti. There is a library for it. There are several libraries for it. None of them are wrong, but you do not actually need any of them — a 200-particle confetti burst is forty lines of plain code, and the version you write yourself looks better because you tuned it.
We will walk through a confetti burst, then generalize to sparkles, snow, and "money rain." The same engine drives all four.
The data model
Every particle is the same five numbers: position (x, y), velocity (vx, vy), rotation rot, rotational velocity vr, and a color. Build an array of 200 of these, seeded randomly. That is the entire state.
Then on each frame, you do not actually re-simulate anything — you compute the particle's position as a pure function of time. Position at time t is start + velocity * t + 0.5 * gravity * t * t. Rotation is start_rot + vr * t. This is what makes the animation deterministic: every frame is independent of every other frame.
Why a pure function of time?
Most particle systems update state every frame: p.x += p.vx * dt. This works, until you want to render to MP4 — then small dt variations accumulate into visible drift between renders. A pure function of time produces the same image at the same t, every time. Render-determinism falls out for free.
This is the same principle behind our deterministic rendering manifesto: never integrate state, always compute from a clock. If you want a different burst, change the seed. If you want the same burst tomorrow, you get it.
The three knobs that matter
Once the engine works, the three numbers that change the feel are:
- Particle count. 50 reads as "splash," 200 as "confetti," 600 as "explosion." Pick the one that matches your moment.
- Gravity. Real-world is ~980 px/s². But video time is compressed — try 600-900 for a confetti shower, 1500+ for a "drop."
- Initial velocity spread. Wider spread means more chaos. For a centered burst, a uniform spherical spread feels right. For a directional flick, bias the velocity.
Generalizing: sparkles and snow
Same engine, different parameters:
- Sparkles: gravity 0, lifetime 1.5s, opacity fades in then out. Spawn continuously rather than as a burst.
- Snow: gravity 100, wind term (small
sin(t * freq)offset onx), opacity 0.7, size variance is high. - Money rain: rectangles with
4:8aspect, gravity 1200, no rotation drift (bills fall flat), low color variance.
Each is a tweak to two or three numbers in the same loop. If you find yourself writing a new particle engine for each effect, you are over-engineering.
What canvas gives you that DOM does not
200 absolutely-positioned <div> elements will render confetti. They will also drop frames at high counts, especially on mobile. A single canvas with 200 fills runs at 60fps on a five-year-old phone.
The rule of thumb: if you have more than ~50 moving elements, switch to canvas. The API is two function calls (fillRect, translate/rotate) and you get back orders-of-magnitude headroom.
Pairing confetti with a payoff
A confetti burst with no anchor reads as noise. Always pair it with a payoff in the center — the headline, the number, the brand mark. The confetti is the punctuation; the payoff is the sentence. See also our notes on motion graphics in 80 lines for more on this principle.
Rendering to MP4
Because the simulation is a pure function of t, rendering to MP4 is the same as rendering to the screen — just capture each frame at fixed t intervals and encode. The HyperFrames render pipeline does exactly this; you get a 30fps MP4 with no frame drops and no dt drift.
The whole point: confetti is forty lines, you understand the math, you can tune the feel, and the output is identical every time you press render. That is the deal.
Cite this postBibTeX · APA · Markdown
@misc{team2026confetti,
author = {HyperFrames Team},
title = {Confetti, sparkles, and other particle tricks in pure CSS},
year = {2026},
url = {https://hyperframes.video/blog/css-confetti-particle-effect},
note = {HyperFrames blog}
}HyperFrames Team. (2026, May 11). Confetti, sparkles, and other particle tricks in pure CSS. HyperFrames. https://hyperframes.video/blog/css-confetti-particle-effect
[Confetti, sparkles, and other particle tricks in pure CSS](https://hyperframes.video/blog/css-confetti-particle-effect) — HyperFrames Team, 2026
We build the deterministic HTML-to-video pipeline at HyperFrames. We write here when we have something concrete to say.
Animated heatmap visualization, rendered to MP4
Build an animated heatmap in plain HTML and CSS — a 12×7 grid where cells fade in with intensity-based color values, scrubbing left-to-right. Deterministic MP4 from JSON.
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.
Kinetic typography for headlines (code, not design school)
Five kinetic typography patterns for headlines, with the CSS and JS that drives each one. No motion designer required.
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.