GenovSvetoslav

Snow Effect that Brings a Winter Mood to Your Website

I built a small script that creates a falling snow effect on a webpage. It works without images or libraries. Everything is done with plain HTML, CSS, and a few lines of JavaScript.

See the snow effect in action


You start by placing a fixed container behind the page content. This container holds every snowflake. Each flake is a small div that uses one of several Unicode snow characters.

<div id="snow"></div>

CSS handles the animation. A single keyframe rule moves the flakes from above the viewport to below it. Opacity fades out near the end which gives a softer finish.

#snow {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: -1;
    overflow: hidden;
}
.snowflake {
    position: absolute;
    top: -26px;
    color: white;
    opacity: 0.8;
    animation: fall linear infinite;
}
@keyframes fall {
    to {
        transform: translateY(110vh);
        opacity: 0;
    }
}

JavaScript creates the flakes. It picks a random character, a random font size, a random horizontal position, and random timing values. These small variations keep the motion from feeling repetitive. The script adjusts the number of flakes based on screen width so a phone shows fewer flakes to keep the content clear while a large desktop can display more without crowding the page.

const container = document.getElementById("snow");
const snowflakeTypes = ["❄", "❅", "❆", "❉", "❋"];

const w = window.innerWidth || document.documentElement.clientWidth;

const numFlakes =
  w < 480 ? 20 :
  w < 768 ? 40 :
  w < 1200 ? 60 :
  80;

for (let i = 0; i < numFlakes; i++) {

    const f = document.createElement("div");
    f.className = "snowflake";
    f.textContent = snowflakeTypes[Math.floor(Math.random() * snowflakeTypes.length)];

    f.style.fontSize = 8 + Math.random() * 18 + "px";
    f.style.left = Math.random() * 100 + "vw";
    f.style.animationDuration = 6 + Math.random() * 12 + "s";
    f.style.animationDelay = Math.random() * 10 + "s";

    container.appendChild(f);
    
}

You can also add a nice touch by making the snow sway with the horizontal movement of the cursor. Demo

let mouseX = 0;
let targetX = 0;
document.addEventListener("mousemove", e => {
  targetX = (e.clientX / window.innerWidth - 0.5) * 80; // max sway
});

function animate() {
  mouseX += (targetX - mouseX) * 0.05;
  container.style.transform = `translateX(${mouseX}px)`;
  requestAnimationFrame(animate);
}
animate();

If you would like a more advanced version of the script, where the snowflakes sway as they fall, pile up at the bottom of the screen, and then slowly melt, you can see a demo here.