When it comes to motion and animations, there is probably nothing I love more than particles. This is why every time I explore new technologies I always end up creating demos with as many particles as I can.

In this post, we’ll make even more particle magic using the Web Animations API to create a firework effect when clicking on a button.

Browser support

At the time I’m writing this article, all major browsers — with the exception of Safari and Internet Explorer — at least partially support the Web Animations API. Safari support can be enabled in the “Experimental Features” developer menu.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up. Desktop Chrome Firefox IE Edge Safari 88 82 No 85 13.1 Mobile / Tablet Android Chrome Android Firefox Android iOS Safari 85 79 81 13.4-13.7

If you’re interested in reproducing the Twitter heart animation you could also have a look at this cool article by Ana Tudor which is another great example of exploding particles on a button.

HTML setup

We won’t need much HTML for this demo. We will use a <button> element but it could be another type of tag element. We could even listen to any click on the page to make particles pop from anywhere if we really wanted to.

<button id="button">Click on me</button>

CSS setup

Since every particle has a few CSS properties in common, we can set them in the global CSS of the page. As you can create custom tag elements in HTML, I will use a <particle> tag name to avoid using semantic tags. But truth is, you could animate <p> , <i> or any tag of your choice.

particle { border-radius: 50%; left: 0; pointer-events: none; position: fixed; top: 0; }

A couple thing to note here:

The particles should not interact with the layout of our page, so we’re setting a fixed position with top and left at 0px each.

position with and at each. We’re also removing pointer events to avoid any user interaction on the HTML particles while they are on the screen.

Because styling the button and the page layout is not really the purpose of this article I will leave that on the side.

JavaScript setup

Here are the six steps we will follow in our JavaScript:

Listen to click event on the button Create 30 <particle> elements and append them into the <body> Set a random width , height and background for every particle Animate each particle from the mouse position to a random place as they fade out Remove the <particle> from the DOM when the animation is complete

Step 1: The click event

// We first check if the browser supports the Web Animations API if (document.body.animate) { // If yes, we add a click listener on our button document.querySelector('#button').addEventListener('click', pop); }

Step 2: The particles

// The pop() function is called on every click function pop(e) { // Loop to generate 30 particles at once for (let i = 0; i < 30; i++) { // We pass the mouse coordinates to the createParticle() function createParticle(e.clientX, e.clientY); } } function createParticle(x, y) { // Create a custom particle element const particle = document.createElement('particle'); // Append the element into the body document.body.appendChild(particle); }

Step 3: Particle width, height and background

function createParticle (x, y) { // [...] // Calculate a random size from 5px to 25px const size = Math.floor(Math.random() * 20 + 5); // Apply the size on each particle particle.style.width = `${size}px`; particle.style.height = `${size}px`; // Generate a random color in a blue/purple palette particle.style.background = `hsl(${Math.random() * 90 + 180}, 70%, 60%)`; }

Step 4: Animate each particle

function createParticle (x, y) { // [...] // Generate a random x & y destination within a distance of 75px from the mouse const destinationX = x + (Math.random() - 0.5) * 2 * 75; const destinationY = y + (Math.random() - 0.5) * 2 * 75; // Store the animation in a variable because we will need it later const animation = particle.animate([ { // Set the origin position of the particle // We offset the particle with half its size to center it around the mouse transform: `translate(${x - (size / 2)}px, ${y - (size / 2)}px)`, opacity: 1 }, { // We define the final coordinates as the second keyframe transform: `translate(${destinationX}px, ${destinationY}px)`, opacity: 0 } ], { // Set a random duration from 500 to 1500ms duration: 500 + Math.random() * 1000, easing: 'cubic-bezier(0, .9, .57, 1)', // Delay every particle with a random value from 0ms to 200ms delay: Math.random() * 200 }); }

Because we have a random delay, the particles waiting to start their animation are visible on the top-left of the screen. To prevent this, we can set a zero opacity on every particle in our global CSS.

particle { /* Same as before */ opacity: 0; }

Step 5: Remove particles after the animation completes

It is important to remove the particle elements from the DOM. Since we create 30 new elements on every click, the browser memory can fill up pretty quickly and cause things to get janky. Here’s how we can do that:

function createParticle (x, y) { // Same as before // When the animation is finished, remove the element from the DOM animation.onfinish = () => { particle.remove(); }; }

Final result

Putting everything together gives us what we’re looking for: a colorful explosion of particle goodness.

CodePen Embed Fallback

Not seeing the animation in the demo? Check if your browser supports the Web Animations API. in the support table at the top of the post.

Be creative!

Because all this is using CSS, it’s pretty simple to modify the particle styles. Here are five examples using various shapes… and even characters!

CodePen Embed Fallback

Or hey, we can even explode the button itself like Zach Saucier did in this post.