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 |
---|---|---|---|---|
84 | 75 | No | 84 | 13.1 |
Mobile / Tablet
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
122 | 123 | 122 | 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 withtop
andleft
at0px
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
andbackground
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.
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!
Or hey, we can even explode the button itself like Zach Saucier did in this post.