JSFiddle - React, Tailwind, and code Playground

by joshmoto

HTML

<snow-fall count="100" mode="page"></snow-fall>

SCSS

body {
    background: #000; /* Dark background for better visibility */
    height: 100vh;
    margin: 0;
    overflow: hidden;
}

:root {
  --snow-fall-intensity: 1; /* Number of snowflakes */
  --snow-fall-drift: 400; /* Sideways drift amount (blizzard effect) */
  --snow-fall-speed-min: 15s; /* Minimum fall speed */
  --snow-fall-speed-max: 45s; /* Maximum fall speed */
  --snow-fall-size: 30px; /* Snowflake size */
  --snow-fall-opacity-min: 0.3; /* Minimum opacity */
  --snow-fall-opacity-max: 1; /* Maximum opacity */
  --snow-fall-color: rgba(255,0,0 , 0.7); /* Snowflake color */
}

JavaScript

class Snow extends HTMLElement {
  static random(t, e) {
    return t + Math.floor(Math.random() * (e - t) + 1);
  }

  static attrs = {
    count: "count",
    mode: "mode",
    text: "text",
  };

  generateCss(t, e) {
    let n = [];

    n.push(`
            :host([mode="element"]) {
                display: block;
                position: relative;
                overflow: hidden;
            }
            :host([mode="page"]) {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                pointer-events: none;
            }
            * {
                position: absolute;
                pointer-events: none;
            }
            :host([text]) * {
                font-size: var(--snow-fall-size, 1em);
                color: var(--snow-fall-color, hsl(0, 100%, 75%)); /* Animated HSL color */
            }
            :host(:not([text])) * {
                width: var(--snow-fall-size, 10px);
                height: var(--snow-fall-size, 10px);
                background: var(--snow-fall-color, hsl(0, 100%, 75%)); /* Animated HSL color */
                border-radius: 50%;
            }
        `);

    let o = { width: 100, height: 100 },
      a = { x: "vw", y: "vh" };

    if (t === "element") {
      o = {
        width: this.firstElementChild.clientWidth,
        height: this.firstElementChild.clientHeight,
      };
      a = { x: "px", y: "px" };
    }

    for (let i = 1; i <= e; i++) {
      let xStart = (Snow.random(1, 100) * o.width) / 100,
        xDrift = (Snow.random(-10, 10) * o.width) / 100,
        duration = Snow.random(10, 30),
        delay = -1 * Snow.random(0, 30),
        scale = 1e-4 * Snow.random(1, 1e4),
        opacity = Snow.random(50, 100) / 100;

      n.push(`
                :nth-child(${i}) {
                    opacity: ${opacity};
                    transform: translate(${xStart}${a.x}, -10px) scale(${scale});
                ...