html {
  background: #444;
  background-image: radial-gradient(ellipse farthest-corner at 50% 20%, #555 0%, darkslategrey 50%, #123 100%);
}
body {
  margin: 0;
}
#confetti {
  width: 100vw;
  height: 100vh;
  position: relative;
  overflow: hidden;
}
@element #confetti div {

  $this {
    position: absolute;
    width: 75px;
    height: 75px;
    backface-visibility: visible;
    z-index: eval('getAttribute`data-distance`');
    background: hsl(eval('getAttribute`data-bg`'),75%,75%);
    box-shadow: hsl(eval('getAttribute`data-bg`'),75%,75%) 0 0 eval('50-getAttribute`data-distance`')px;
    transform:
      scale(eval('getAttribute`data-distance`/100'))
      rotateX(eval('getAttribute`data-x`')deg)
      rotateY(eval('getAttribute`data-y`')deg)
      rotateZ(eval('getAttribute`data-z`')deg)
    ;
    top: eval('getAttribute`data-top`')px;
    left: eval('getAttribute`data-left`')px;
  }

}
// Create confetti
window.addEventListener('load', function(){

  var wrapper = document.createElement('section')
  wrapper.id = 'confetti'
  document.body.appendChild(wrapper)

  for (var i=60; i--;) {

    var tag = document.createElement('div')

    tag.setAttribute('data-top', Math.ceil(Math.random()*wrapper.offsetHeight*2)-wrapper.offsetHeight)
    tag.setAttribute('data-left', Math.ceil(Math.random()*wrapper.offsetWidth*2)-wrapper.offsetWidth)

    tag.setAttribute('data-bg', Math.ceil(Math.random()*360))
    tag.setAttribute('data-distance', Math.ceil(Math.random()*100))
    tag.setAttribute('data-x', Math.ceil(Math.random()*360))
    tag.setAttribute('data-y', Math.ceil(Math.random()*360))
    tag.setAttribute('data-z', Math.ceil(Math.random()*360))

    wrapper.appendChild(tag)

  }

  requestAnimationFrame(loop)

})

function loop (){

  var tag = document.querySelectorAll('#confetti div')

  for (var i=0; i<tag.length; i++) {

    var top = parseFloat(tag[i].getAttribute('data-top'))
    var left = parseFloat(tag[i].getAttribute('data-left'))
    var distance = parseFloat(tag[i].getAttribute('data-distance'))
    var x = parseFloat(tag[i].getAttribute('data-x'))
    var y = parseFloat(tag[i].getAttribute('data-y'))
    var z = parseFloat(tag[i].getAttribute('data-z'))

    tag[i].setAttribute('data-top', top+1)
    tag[i].setAttribute('data-left', left+1)
    tag[i].setAttribute('data-x', x+2)
    tag[i].setAttribute('data-y', y+2)
    tag[i].setAttribute('data-z', z+2)

  }

  EQCSS.apply()
  requestAnimationFrame(loop)
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/eqcss/1.7.0/EQCSS.min.js