Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exploding particle: Animating with CSS

I'd like to simulate a particle explosion, from the center of a screen out to the edges (In CSS, and I promise to not use this for nefarious purposes)

Here's a visual so you know what I'm talking about:

BEFORE:

BEFORE

AFTER:

AFTER

I've tried using the following HTML/CSS/JS, but it doesn't work (dots stay still in the middle of the screen):

The HTML is just this:

<div id="animated"></div>

The CSS:

// SCSS
#animated {
  position: relative; 
  width: 100%;
  height: 100%;
  overflow: hidden;

  .particle {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 10px;
    height: 10px;
    transition: transform 1s ease-in-out;

    &.on {
      transform: translate(-30vw, -30vh);
    }

    &::after {
      position: absolute;
      content: "";
      width: 10px;
      height: 10px;
      border-radius: 50%;
      background: red;
    }
  }
}

And the Javascript:

document.addEventListener('DOMContentLoaded', onLoad);

function onLoad() {
  // animate
  for(var i = 0; i < 360; i+=5) {
    const particle = createParticle(animated, i);
  }
}

function createParticle(parentElem, rotation) {
  const particle = document.createElement('div');
  particle.style.transform = `rotate(${rotation}deg)`;
  particle.classList.add('particle');
  particle.classList.add('on'); // turn on
  parentElem.appendChild(particle);

  return particle;
}

Here's a link to a CodePen: https://codepen.io/floatingrock/pen/KKpxpvJ

like image 521
FloatingRock Avatar asked Jun 16 '26 19:06

FloatingRock


1 Answers

Here is an idea with CSS variable where it's easy to adjust with few code.

Run on full screen for better result:

document.addEventListener('DOMContentLoaded', onLoad);

function onLoad() {
  let parentElem = document.querySelector('.container');
  for (var i = 0; i < 360; i += 10) {
    const particle = document.createElement('div');
    particle.style = `--r:${i}deg`;
    parentElem.appendChild(particle);
  }
}
.container {
  width: 20px;
  height: 20px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.container>div {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: red;
  transform: rotate(var(--r, 0deg)) translate(0);
  animation: splash 1s infinite alternate 1s;
}

@keyframes splash {
  to {
    transform: rotate(var(--r, 0deg)) translate(44vmin);
  }
}
<div class="container">
</div>

You can consider different delay for another kind of animation:

document.addEventListener('DOMContentLoaded', onLoad);

function onLoad() {
  let parentElem = document.querySelector('.container');
  for (var i = 0; i < 360; i += 10) {
    const particle = document.createElement('div');
    particle.style = `--r:${i}deg;--d:${(i/360)}s`;
    parentElem.appendChild(particle);
  }
}
.container {
  width: 20px;
  height: 20px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.container>div {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: red;
  transform: rotate(var(--r, 0deg)) translate(0);
  animation: splash 1s infinite alternate var(--d,0s);
}

@keyframes splash {
  to {
    transform: rotate(var(--r, 0deg)) translate(44vmin);
  }
}
<div class="container">
</div>

We can still optimize the code with less CSS:

document.addEventListener('DOMContentLoaded', onLoad);

function onLoad() {
  let parentElem = document.querySelector('.container');
  for (var i = 0; i < 360; i += 10) {
    const particle = document.createElement('div');
    particle.style = `--r:${i}deg`;
    parentElem.appendChild(particle);
  }
}
.container > div {
  position: fixed;
  top: 50%;
  left: 50%;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: red;
  transform:translate(-50%, -50%) rotate(var(--r, 0deg)) translate(0);
  animation: splash 1s infinite alternate 1s;
}

@keyframes splash {
  to {
    transform:translate(-50%, -50%) rotate(var(--r, 0deg)) translate(calc(50vmin - 10px));
  }
}


/* Irrelevant styles */
html {
  height:100%;
  border:1px solid blue; /* screen border*/
  box-sizing:border-box;
  background:linear-gradient(green,green) center/10px 10px no-repeat; /* the center of the screen */
}
body {
 margin:0;
}
<div class="container">
</div>

The order of transformation is important. Related: Why does order of transforms matter? rotate/scale doesn't give the same result as scale/rotate

like image 149
Temani Afif Avatar answered Jun 19 '26 14:06

Temani Afif