<main id=app>
  <h1>
    Obligatory Holiday Snow Falling
  </h1>
  <p>Using a new, lightweight, high-performance, canvas-based particle system soon to be available!</p>
  
  
  <a href="https://github.com/simeydotme/sparticles" class="link">follow the progress of Sparticles on Github</a>
</main>
* {
  box-sizing: border-box;
}

body, html {
  color: white;
  background: #1e2021;
  padding: 0;
  margin: 0;
  font-family: "Heebo", sans-serif;
  height: 100%;
  width: 100%;
}

main {
  width: 100%;
  height: 100%;
  position: relative;
  padding-top: 30px;
  z-index: 1;
  background-image: 
    linear-gradient(rgba(30,32,33,0.2), rgba(30,42,53,1)), url("https://images.unsplash.com/photo-1552910996-e666ad64695c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80");
  background-size: cover;
  background-position: bottom center;
}

.stats {
  position: absolute;
  left: 10px;
  top: 0;
}

#app canvas {
  z-index: -1;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  mix-blend-mode: color-dodge;
}

h1, p {
  text-align: center;
  margin: 0 auto;
  max-width: 400px;
}

h1 {
  font-size: 50px;
  font-weight: 100;
  font-family: "Mountains of Christmas", cursive;
  margin: 0 auto 15px;
}

.dg.ac {
  z-index: 2!important;
}

.link {
  display: block;
  position: absolute;
  bottom: 20px;
  width: 100%;
  margin: 0 auto;
  text-align: center;
  color: white;
}
View Compiled
//
// I'm hotlinking to some SVG images from flaticon.com
// for use as the snowflakes. I hope that remains possible
// especially with the below attribution;
//
// ❄ Icons made by Freepik from www.flaticon.com
// ❄ https://www.flaticon.com/packs/snowflakes
//

let colorType = {
  type: "multi"
};

let colors = {
  color1: "rgba(255,255,255,1)",
  color2: "rgba(142,217,222,1)",
  color3: "rgba(232,248,255,1)",
  color4: "rgba(135,143,145,1)"
};

let options = {
  alphaSpeed: 10,
  alphaVariance: 1,
  color: [colors.color1, colors.color2, colors.color3, colors.color4],
  composition: "source-over",
  count: 350,
  direction: 161,
  float: 0.75,
  glow: 0,
  imageUrl: [
    "https://image.flaticon.com/icons/svg/23/23858.svg",
    "https://image.flaticon.com/icons/svg/23/23883.svg",
    "https://image.flaticon.com/icons/svg/23/23889.svg",
    "https://image.flaticon.com/icons/svg/24/24296.svg",
    "https://image.flaticon.com/icons/svg/23/23901.svg",
    "https://image.flaticon.com/icons/svg/24/24286.svg"
  ],
  maxAlpha: 2,
  maxSize: 22,
  minAlpha: -0.2,
  minSize: 4,
  parallax: 1.75,
  rotation: 0.5,
  shape: "image",
  speed: 3,
  style: "fill",
  twinkle: false,
  xVariance: 5,
  yVariance: 0,
};

window.onload = function() {
  initStats();
  initSparticles();
  initGui();
}

window.initSparticles = function() {
  var $main = document.querySelector("main");
  window.mySparticles = new sparticles.Sparticles($main,options);
};

window.initStats = function() {
  var stats = new Stats();
  stats.domElement.classList.add("stats");
  document.body.appendChild(stats.domElement);
  function statsDisplay() {
    stats.begin();
    stats.end();
    requestAnimationFrame(statsDisplay);
  }
  requestAnimationFrame(statsDisplay);
};

window.initGui = function() {
  const s = window.mySparticles;
  const shapes = ["circle", "square", "triangle", "diamond", "line", "image"];
  const styles = ["fill", "stroke", "both"];
  const colorOptions = ["single", "multi", "rainbow"];
  const composites = [
    "source-over",
    "source-in",
    "source-out",
    "source-atop",
    "destination-over",
    "destination-in",
    "destination-out",
    "destination-atop",
    "lighter",
    "copy",
    "xor",
    "multiply",
    "screen",
    "overlay",
    "darken",
    "color-dodge",
    "color-burn",
    "hard-light",
    "soft-light",
    "difference",
    "exclusion",
    "hue",
    "saturation",
    "color",
    "luminosity"
  ];
  const rerender = () => {
    s.createColorArray();
    s.createShapeArray();
    s.setupOffscreenCanvasses(function() {
      s.createSparticles();
    });
  };
  var rerenderColors = function(v) {
    if (colorType.type === "rainbow") {
      s.settings.color = "rainbow";
    } else if (colorType.type === "single") {
      s.settings.color = colors.color1;
    } else {
      s.settings.color = Object.keys(colors).map(i => {
        return colors[i];
      });
    }
    rerender();
  };

  const gui = new dat.GUI({ load: options });
  const part = gui.addFolder("Particles");
  part.open();
  part.add(s.settings, "count", 1, 500, 1).onFinishChange(rerender);
  part.add(s.settings, "shape", shapes).onFinishChange(rerender);
  part.add(s.settings, "style", styles).onFinishChange(rerender);
  const image = part.addFolder("Image");
  // image.add(s.settings, "imageUrl").onFinishChange(rerender);
  part.add(s.settings, "minSize", 1, 50, 1).onFinishChange(rerender);
  part.add(s.settings, "maxSize", 1, 50, 1).onFinishChange(rerender);
  const anim = gui.addFolder("Animation");
  anim.add(s.settings, "direction", 0, 360, 1).onFinishChange(rerender);
  anim.add(s.settings, "speed", 0, 100, 0.1).onFinishChange(rerender);
  anim.add(s.settings, "rotation", 0, 100, 0.1).onFinishChange(rerender);
  const move = anim.addFolder("Movement");
  move.add(s.settings, "parallax", 0, 10, 0.1).onFinishChange(rerender);
  move.add(s.settings, "float", 0, 10, 0.1).onFinishChange(rerender);
  move.add(s.settings, "xVariance", 0, 10, 0.1).onFinishChange(rerender);
  move.add(s.settings, "yVariance", 0, 10, 0.1).onFinishChange(rerender);
  const vis = gui.addFolder("Visual");
  vis.add(s.settings, "glow", 0,50).onFinishChange(rerender);
  vis.add(s.settings, "composition", composites).onFinishChange(rerender);
  const alpha = vis.addFolder("Alpha");
  alpha.add(s.settings, "twinkle").onFinishChange(rerender);
  alpha.add(s.settings, "minAlpha", -2, 2, 0.1).onFinishChange(rerender);
  alpha.add(s.settings, "maxAlpha", -2, 2, 0.1).onFinishChange(rerender);
  alpha.add(s.settings, "alphaSpeed", 0, 50, 1).onFinishChange(rerender);
  alpha.add(s.settings, "alphaVariance", 0, 20, 1).onFinishChange(rerender);
  const color = vis.addFolder("Color");
  color.open();
  color.add(colorType, "type", colorOptions).onFinishChange(rerenderColors);
  color.addColor(colors, "color1").onFinishChange(rerenderColors);
  color.addColor(colors, "color2").onFinishChange(rerenderColors);
  color.addColor(colors, "color3").onFinishChange(rerenderColors);
  color.addColor(colors, "color4").onFinishChange(rerenderColors);
  const control = gui.addFolder("Controls");
  control.add(s,"start");
  control.add(s,"stop");
};

External CSS

  1. https://fonts.googleapis.com/css?family=Mountains+of+Christmas:400,700|Heebo:100,300,400,500,700,800,900

External JavaScript

  1. https://rawcdn.githack.com/simeydotme/sparticles/86169e200cc64b03293d69858c321ad5623f8a6e/dist/sparticles.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js