We see confetti everywhere on the web, and seemingly more and more these days. It must mean we are getting happier as a culture, and better at what we do, and therefore more deserving of rewards, right? Or, maybe it’s just a good marketing retention trick, designed to bait you into that next click. Or maybe it’s somewhere in the middle: giving a user a small token of delight is always worth it, no matter what the context. Thankfully as an engineer, the philosophical implications of confetti placement is not my primary concern. But, making confetti look good is. And though it’s hard to believe in this day and age that there wasn’t a public React component out there that was lightweight, supported cross-platform, and good looking, this was the dismal truth. This is why we set out to build our own.

View the react-confetti-explosion repo.

One popular confetti effect seen across the web is this, which uses HTML canvas. It’s clean, performant, and lovely looking. The only problem is raining confetti. While this is ideal for filling a background, we needed a single explosion that could be placed anywhere in the DOM, and triggered on demand. In order to rewrite this library to be explosive rather than raining would either require importing a whole new physics library or painstakingly creating your own particle generator, and even then you might run into problems positioning/overlaying the canvas on DOM elements. So the logical choice was to approach this from a pure CSS perspective. But could that be done? Scouring the web for CSS confetti animations did not yield inspiring results, to say the least.

It turns out most of what you need to basically emulate exploding confetti exists already with CSS properties. How do you make a particle look like it gets tossed out from an origin and follow a curved motion path down to the floor? The essential idea lies in adding motion curves to a single element on two separate axis, x and y, as seen in this tutorial.

So if you build the element with two targetable elements:

<div class="wrapper">
  <div class="particle"></div>
</div>

You can animate them with bezier curves separately like this:

'@keyframes x-axis': {
  to: {
    transform: `translateX(100px)`,
  },
},
'@keyframes y-axis': {
  to: {
    transform: `translateY(100px)`,
  },
}
...
wrapper: {
  animation: `x-axis 1s forwards cubic-bezier(0, -1, 0, 1)`,
},
particle: {
  animation: `y-axis 1s forwards cubic-bezier(0, -1, 0, 2)`,
}

And you can endlessly tweak those cubic-bezier values until you find just the right ratios to give you that organic look of a little piece of paper shooting out–then floating–through the air.

We also need to spin the confetto (yes, that’s confetti singular) on its own axis. Thankfully that’s easy with CSS too using rotate3d.

'@keyframes rotation': {
  to: {
    transform: `rotate3d(1, 0, 1, 360deg)`,
  },

Here you can rotate on all, some, or none of the x, y, z axis for each particle. Then we can tweak the dimensions of the particles. Do we want a rectangle or a circle, ultimately maybe a mix of both?

Being satisfied with the way one particle behaves is just the beginning. Then it’s a matter of applying that to a larger set by carefully applying a speed, motion path, and landing destination point for each particle emanating from an origin in a radial fashion. For each degree/direction a particle emanates, we need slightly different motion paths. These parameters can be controlled by the bezier-curve of its x and y axis (mostly the x). We don’t need to get to deep into it, but let’s just say there a fair bit of guesstimation work here if you don’t want to spend the time to write your own algorithm for determining ideal cubic-bezier representations for an element exploding with some initial force, direction, particle mass, air friction, in a gravitational environment of 32ft/sec/sec, at 84.2% humidity, 53 degree dew point, and a slight chance of a tornado 3,721 miles away.

Even if you could write such an algorithm, you’d end up with a perfectly uniform explosion. While this might work great for a fireworks-type display, confetti is random, chaotic, volatile. It’s Italian after all. So why not skip the really complicated math if we need to include chaos anyway? Estimating explosion curves actually works to our advantage here — imperfection looks more realistic as long as they vary sufficiently particle to particle. More “chaos” can be achieved by tweaking those bezier curves further to get more drastic and wild curves. Then tweak the percentage of particles that have randomness, as well as the extent of the randomness: Too little and the confetti will look more like fireworks, too much and it will start looking like a swarm of colored bees.

Somewhere in the middle is just right:

So in the end, it is possible. But more to the point: it looks good, is flexible, is performant across all modern browsers/devices (as long as you stay under 400-ish particles), and is small (using only two minor dependencies and amounting to 34K unpacked). Of all ways to animate in the browser, CSS is one of the cheapest, if not the cheapest in this particular case (it helps that we don’t have gradients or shadows on anything). No need for an SVG animation library, no need for a particle generating algorithm on canvas, and no need to build your whole website in Flash! (haha just kidding).

Unlock commercial real estate insights and opportunities with ease Start Searching

Related Posts