CSS Particle Buttons

Quickly create beautiful CSS Particle animations

How to use:
To add a button to your own page, simply download the .zip file, or copy the CSS and Javascript individually. You can add the html of the button wherever you want on your page.
<div>		
    <button class=”particleButton”>Click Me</button>	
    <div class=”particleButton particles”></div>	
</div>	
If you decide to create the buttons dynamically, make sure to add an initial listener that adds the .animated class to the .particles-div on the first click.
You may also want to add the animation to a different element or trigger it at a different event. To do so, simply copy the @keyframes and background-image string and add it to your desired element.
How it works
This generator makes use of the background-image property and the ::after pseudo-selector. In the background-image property we can define multiple shapes and individually control the movement and size of each with the background-position and background-size properties. Based on the chosen settings, the generator will create the particles and perform the physics/movement calculations. This is then translated into the CSS background-image property and a @keyframes animation. Each particle is defined by one background-image.

In detail:
The button consists of two elements: A button element and a div element beneath that button.
<div class=”buttonWrap”>	
    <button class=”particleButton”>Click me</button>	
    <div class=”particleButton particles animated”></div>	
</div>	
Both elements are set to position: absolute and are positioned exactly on top of each other. The .particles-element itself has no appearance. Its ::after element is where we add the @keyframes animation. We do this by adding the class .animated to the .particles-element.
.particleButton {	
    position: absolute;	
    width: 90px;	
    height: 90px;	
    left: 50%;	
    top: 50%;	
    transform: translate(-50%,-50%);	
}
.particles {
    z-index: -1;
    background: none !important;
    pointer-events: none;
}
.animated::after {	
    background-image: * All the Particles *	
    animation: particleAnimation linear 1s forwards;	
}
@keyframes particleAnimation { 	
    * All the particles sizes and positions *	
}
We could also add the animation to the .particles element directly but then we would need to apply a transform: translate(-50%,-50%) to it every keyframe, making the animation string longer than necessary.

In fact we could even add the animation directly to the ::after element of the button, getting rid of the second element completely like in this example. However that would result in the particles rendering in front of the buttons background.


To trigger the animation each time we click button, we set the .particles-element to animation: none; when the button is active:
button.particleButton:active ~ .particles {	
    animation: none;	
    background-size: 0;	
}	
A problem with this setup is that the animation will automatically start playing once the page is loaded. To avoid that, we’ll use a bit of Javascript, only adding the .animated class to the element the first time the button is clicked:
window.onload = () => {
    let btn = document.querySelector("button.particleButton")	
    let btnBG = btn.parentNode.querySelector(.particles)	

    let initalListener = () => {	
        btnBG.classList.add("animated")	
        btn.removeEventListener("click", initalListener)	
    }
    btn.addEventListener("click", initalListener)	
}
This will add an EventListener to all the particle-buttons on pageload and only add the .animated class to the .particles-element the first time the button is clicked.
Browser support
These buttons should work in all modern browsers: They do not work in Internet Explorer.

Other notes:
Creating animations with many frames and particles can cause your site to become laggy, so use with caution and thoroughly test before adding this into production.

Chrome sometimes displays some weird rendering artifacts when scaling the entire .particles element. When particles are drawn on the edge of the element and the element is scaled down, there will be ugly artifacts left at the previous edges, as if the previous image isn't properly cleared.

You can use the prefers-reduced-motion CSS media feature to hide motion-intense animations from users that opted for less animations on their system.
About this tool
While working on a game I was making, I wanted to add a nice particle effect to the in-game buttons. Searching for a CSS solution I found this awesome Codepen by Nour Saud. Then I wondered if its possible to create such animations automatically rather than defining each particle, its size and position at each keyframe one by one. After all, particles are supposed to be somewhat random.

So I started creating a particle system and dynamically generating CSS strings. After playing around with an increasing number of parameters, I noticed that you can achieve quite diverse results, so I decided build this tool to make it easier for everyone to create beautiful particle effects. Skip forward a few weeks and this tool was born 😊.


The source code is available on Github.