@manufosela/animation-snowcss

@manufosela/animation-snowcss

CSS-based snow effect web component built with Lit 3

ANIMATION SNOW CSS

CSS Snow Effect

Pure CSS animated snowflakes with gentle falling and drift

200
2

Usage

<!-- Install -->
npm install @manufosela/animation-snowcss

<!-- Import -->
<script type="module">
  import '@manufosela/animation-snowcss';
</script>

<!-- Use -->
<animation-snowcss
  num-snowflakes="200"
  speed="2"
  color="white"
  active
></animation-snowcss>

Attributes

Attribute Type Default Description
num-snowflakes Number 200 Number of snowflakes
speed Number 2 Fall speed multiplier
color String white Snowflake color (any CSS color)
active Boolean true Whether animation is visible

Methods

Method Description
start() Show and resume the snow animation
stop() Hide the snow animation with a fade transition
← animation-components
Demo code (CodePen-ready HTML, CSS, JS)
HTML (html)
<animation-snowcss id="snow" num-snowflakes="200" speed="2" color="white"></animation-snowcss>

    <h1>ANIMATION SNOW CSS</h1>

    <div class="demo-container">
      <div class="scene">
        <h2>CSS Snow Effect</h2>
        <p>Pure CSS animated snowflakes with gentle falling and drift</p>
      </div>

      <div class="controls">
        <div class="control-group">
          <label for="numSnowflakes">Snowflakes</label>
          <input type="range" id="numSnowflakes" min="20" max="400" value="200" />
          <span class="value-display" id="numSnowflakesVal">200</span>
        </div>
        <div class="control-group">
          <label for="speed">Speed</label>
          <input type="range" id="speed" min="0.2" max="6" step="0.1" value="2" />
          <span class="value-display" id="speedVal">2</span>
        </div>
        <div class="control-group">
          <label for="color">Color</label>
          <input type="color" id="color" value="#ffffff" />
        </div>
        <div class="control-group" style="justify-content: flex-end;">
          <div class="btn-group">
            <button id="btnStart">Start</button>
            <button id="btnStop">Stop</button>
          </div>
        </div>
      </div>

      <div class="info-section">
        <h3>Usage</h3>
        <pre>&lt;!-- Install --&gt;
npm install @manufosela/animation-snowcss

&lt;!-- Import --&gt;
&lt;script type="module"&gt;
  import '@manufosela/animation-snowcss';
&lt;/script&gt;

&lt;!-- Use --&gt;
&lt;animation-snowcss
  num-snowflakes="200"
  speed="2"
  color="white"
  active
&gt;&lt;/animation-snowcss&gt;</pre>
      </div>

      <div class="info-section">
        <h3>Attributes</h3>
        <table>
          <thead>
            <tr>
              <th>Attribute</th>
              <th>Type</th>
              <th>Default</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td><code>num-snowflakes</code></td>
              <td>Number</td>
              <td><code>200</code></td>
              <td>Number of snowflakes</td>
            </tr>
            <tr>
              <td><code>speed</code></td>
              <td>Number</td>
              <td><code>2</code></td>
              <td>Fall speed multiplier</td>
            </tr>
            <tr>
              <td><code>color</code></td>
              <td>String</td>
              <td><code>white</code></td>
              <td>Snowflake color (any CSS color)</td>
            </tr>
            <tr>
              <td><code>active</code></td>
              <td>Boolean</td>
              <td><code>true</code></td>
              <td>Whether animation is visible</td>
            </tr>
          </tbody>
        </table>
      </div>

      <div class="info-section">
        <h3>Methods</h3>
        <table>
          <thead>
            <tr>
              <th>Method</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td><code>start()</code></td>
              <td>Show and resume the snow animation</td>
            </tr>
            <tr>
              <td><code>stop()</code></td>
              <td>Hide the snow animation with a fade transition</td>
            </tr>
          </tbody>
        </table>
      </div>

      <a class="back-link" href="https://manufosela.dev/animation-components/">
        ← animation-components
      </a>
    </div>
CSS (css)
:root {
  --bg: #0c0f14;
  --bg-elevated: #141923;
  --bg-panel: #171d28;
  --border: #262f3f;
  --text: #f4f6fb;
  --text-muted: #a7b0c2;
  --text-dim: #7d879b;
  --accent: #ff8a3d;
  --accent-strong: #ff6a00;
  --accent-soft: rgba(255, 138, 61, 0.16);
  --shadow: 0 20px 50px rgba(5, 8, 14, 0.45);
  --radius-lg: 22px;
  --radius-md: 14px;
  --radius-sm: 10px;
  --max-width: 1160px;
}

* {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      h1 {
        text-align: center;
        padding: 2rem;
        font-weight: 300;
        letter-spacing: 4px;
        color: #e8f4ff;
        text-shadow: 0 0 20px rgba(220, 240, 255, 0.6);
      }

      .demo-container {
        max-width: 900px;
        margin: 0 auto;
        padding: 0 1rem 4rem;
        position: relative;
        z-index: 1;
      }

      .scene {
        border: 1px solid rgba(220, 240, 255, 0.2);
        border-radius: 16px;
        overflow: hidden;
        margin-bottom: 2rem;
        padding: 4rem 2rem;
        text-align: center;
        background: rgba(14, 22, 33, 0.6);
        backdrop-filter: blur(2px);
      }

      .scene h2 {
        font-size: 2.5rem;
        font-weight: 200;
        letter-spacing: 6px;
        color: rgba(255, 255, 255, 0.9);
        text-shadow: 0 2px 20px rgba(220, 240, 255, 0.4);
        margin-bottom: 0.75rem;
      }

      .scene p {
        font-size: 1.1rem;
        color: rgba(220, 240, 255, 0.55);
      }

      .controls {
        display: flex;
        flex-wrap: wrap;
        gap: 1.5rem;
        justify-content: center;
        padding: 1.5rem;
        background: rgba(220, 240, 255, 0.04);
        border: 1px solid rgba(220, 240, 255, 0.15);
        border-radius: 12px;
        margin-bottom: 2rem;
      }

      .control-group {
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        min-width: 150px;
      }

      .control-group label {
        font-size: 0.875rem;
        color: #c8e4ff;
        opacity: 0.8;
      }

      input[type='range'] {
        width: 150px;
        accent-color: #c8e4ff;
      }

      input[type='color'] {
        width: 50px;
        height: 32px;
        border: 1px solid rgba(220, 240, 255, 0.3);
        border-radius: 6px;
        background: transparent;
        cursor: pointer;
      }

      .value-display {
        font-size: 0.8rem;
        color: rgba(220, 240, 255, 0.45);
      }

      button {
        padding: 0.75rem 1.5rem;
        border: 1px solid rgba(220, 240, 255, 0.6);
        border-radius: 8px;
        background: transparent;
        color: #c8e4ff;
        font-size: 0.9rem;
        letter-spacing: 1px;
        cursor: pointer;
        transition: background 0.2s, color 0.2s;
      }

      button:hover {
        background: rgba(220, 240, 255, 0.12);
      }

      .btn-group {
        display: flex;
        gap: 0.75rem;
        align-items: center;
      }

      .info-section {
        background: rgba(220, 240, 255, 0.03);
        border: 1px solid rgba(220, 240, 255, 0.12);
        border-radius: 12px;
        padding: 1.5rem;
        margin-bottom: 1.5rem;
      }

      .info-section h3 {
        color: #c8e4ff;
        font-weight: 400;
        margin-bottom: 1rem;
        letter-spacing: 2px;
        font-size: 0.95rem;
        text-transform: uppercase;
      }

      pre {
        background: rgba(0, 0, 0, 0.4);
        border-radius: 8px;
        padding: 1rem;
        overflow-x: auto;
        font-size: 0.85rem;
        color: #b8d8f4;
        line-height: 1.6;
      }

      table {
        width: 100%;
        border-collapse: collapse;
        font-size: 0.875rem;
      }

      th, td {
        text-align: left;
        padding: 0.6rem 0.8rem;
        border-bottom: 1px solid rgba(220, 240, 255, 0.08);
      }

      th {
        color: #c8e4ff;
        font-weight: 400;
        text-transform: uppercase;
        letter-spacing: 1px;
        font-size: 0.8rem;
      }

      td code {
        background: rgba(220, 240, 255, 0.1);
        padding: 0.1rem 0.4rem;
        border-radius: 4px;
        font-size: 0.8rem;
        color: #b8d8f4;
      }

      .back-link {
        display: block;
        text-align: center;
        padding: 1rem;
        color: rgba(220, 240, 255, 0.4);
        text-decoration: none;
        font-size: 0.875rem;
        letter-spacing: 1px;
      }

      .back-link:hover {
        color: #c8e4ff;
      }
JS (js)
const snow = document.getElementById('snow');

      const numSnowflakesInput = document.getElementById('numSnowflakes');
      const speedInput = document.getElementById('speed');
      const colorInput = document.getElementById('color');
      const numSnowflakesVal = document.getElementById('numSnowflakesVal');
      const speedVal = document.getElementById('speedVal');

      numSnowflakesInput.addEventListener('input', () => {
        numSnowflakesVal.textContent = numSnowflakesInput.value;
        snow.setAttribute('num-snowflakes', numSnowflakesInput.value);
      });

      speedInput.addEventListener('input', () => {
        speedVal.textContent = Number(speedInput.value).toFixed(1);
        snow.setAttribute('speed', speedInput.value);
      });

      colorInput.addEventListener('input', () => {
        snow.setAttribute('color', colorInput.value);
      });

      document.getElementById('btnStart').addEventListener('click', () => snow.start());
      document.getElementById('btnStop').addEventListener('click', () => snow.stop());