
Yet another elegant snowfall effect that combines exquisite SVG snowflakes, responsive cursor interactions, and a twinkling star background.
Features:
- Snowflakes respond to cursor movement.
- Random initial snowflake placements.
- A gradient-simulated wintry night sky featuring twinkling stars and occasional shooting stars enhances the atmosphere.
- Programmatically creates unique snowflake designs. Varies size, complexity, and visual details.
How to use it:
1. Create two div elements within your HTML document. One will contain the message displayed at the beginning, and the other will serve as the container for the entire snowfall effect:
<div id="message-container"> CSSScript </div> <div id="snowfall-container"></div>
2. Add the necessary CSS styles to position the elements and define the appearance of the snowflakes, stars, and animations:
#snowfall-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
overflow: hidden;
}
.snowflake {
position: absolute;
user-select: none;
transition: transform 0.3s ease, opacity 0.3s ease;
will-change: transform, opacity;
}
#message-container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #e0f7fa;
font-family: "Mountains of Christmas", cursive;
font-size: 4rem;
text-align: center;
z-index: 10;
opacity: 0;
transition: opacity 1s ease;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5), 0 0 5px rgba(224, 247, 250, 0.7);
background: rgba(0, 0, 0, 0.3);
padding: 20px;
border-radius: 10px;
}
.star {
position: absolute;
width: 2px;
height: 2px;
background: white;
border-radius: 50%;
opacity: 0;
animation: twinkle 5s infinite;
}
@keyframes twinkle {
0%,
20%,
50%,
70%,
100% {
opacity: 0;
}
25%,
55%,
75% {
opacity: 1;
}
}3. Use JavaScript to create, animate, and manage the snowflakes and background stars:
class SnowfallAnimation {
constructor() {
this.container = document.getElementById("snowfall-container");
this.messageContainer = document.getElementById("message-container");
this.snowflakes = [];
this.snowflakeTypes = [
this.createSnowflakeSVG(30, 6),
this.createSnowflakeSVG(40, 8),
this.createSnowflakeSVG(25, 4)
];
this.initializeSnowflakes();
this.createStars();
}
createSnowflakeSVG(size, complexity) {
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("width", size);
svg.setAttribute("height", size);
svg.setAttribute("viewBox", `0 0 ${size} ${size}`);
const centerX = size / 2;
const centerY = size / 2;
const radius = size / 2;
for (let i = 0; i < complexity; i++) {
const angle = ((Math.PI * 2) / complexity) * i;
const endX = centerX + radius * Math.cos(angle);
const endY = centerY + radius * Math.sin(angle);
const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
line.setAttribute("x1", centerX);
line.setAttribute("y1", centerY);
line.setAttribute("x2", endX);
line.setAttribute("y2", endY);
line.setAttribute("stroke", "rgba(255,255,255,0.8)");
line.setAttribute("stroke-width", "2");
svg.appendChild(line);
// Add additional details
for (let j = 1; j <= 2; j++) {
const detailAngle = angle + (Math.PI / complexity) * j;
const detailX = centerX + (radius / 2) * Math.cos(detailAngle);
const detailY = centerY + (radius / 2) * Math.sin(detailAngle);
const detailLine = document.createElementNS(
"http://www.w3.org/2000/svg",
"line"
);
detailLine.setAttribute("x1", (centerX + endX) / 2);
detailLine.setAttribute("y1", (centerY + endY) / 2);
detailLine.setAttribute("x2", detailX);
detailLine.setAttribute("y2", detailY);
detailLine.setAttribute("stroke", "rgba(255,255,255,0.5)");
detailLine.setAttribute("stroke-width", "1");
svg.appendChild(detailLine);
}
}
return svg;
}
initializeSnowflakes() {
const numSnowflakes = window.innerWidth < 768 ? 50 : 100;
for (let i = 0; i < numSnowflakes; i++) {
const snowflake = document.createElement("div");
snowflake.classList.add("snowflake");
// Randomly select the snowflake SVG
const svgType = this.snowflakeTypes[
Math.floor(Math.random() * this.snowflakeTypes.length)
];
snowflake.appendChild(svgType.cloneNode(true));
// Initial positioning to form the message
snowflake.style.position = "absolute";
snowflake.style.left = `${Math.random() * 100}%`;
snowflake.style.top = `${Math.random() * 100}%`;
snowflake.style.opacity = `${Math.random() * 0.5 + 0.5}`;
this.snowflakes.push({
element: snowflake,
speed: Math.random() * 3 + 1,
xOffset: Math.random() * 2 - 1,
yOffset: Math.random() * 2 - 1
});
this.container.appendChild(snowflake);
}
this.formMessage();
}
formMessage() {
const messageWidth = this.messageContainer.offsetWidth;
const messageHeight = this.messageContainer.offsetHeight;
this.snowflakes.forEach((flake, index) => {
const rect = this.messageContainer.getBoundingClientRect();
const xPos = rect.left + Math.random() * rect.width;
const yPos = rect.top + Math.random() * rect.height;
flake.element.style.transition = "all 2s cubic-bezier(0.4, 0.0, 0.2, 1)";
flake.element.style.transform = `translate(${
xPos - window.innerWidth / 2
}px, ${yPos - window.innerHeight / 2}px)`;
flake.element.style.opacity = "1";
});
setTimeout(() => {
this.messageContainer.style.opacity = "1";
setTimeout(() => {
this.messageContainer.style.opacity = "0";
this.startSnowfall();
}, 3000);
}, 2000);
}
startSnowfall() {
this.snowflakes.forEach((flake) => {
flake.element.style.transition = "none";
this.animateSnowflake(flake);
});
// Add cursor interaction
document.addEventListener("mousemove", (e) => this.handleMouseMove(e));
}
animateSnowflake(flake) {
const animate = () => {
const rect = flake.element.getBoundingClientRect();
let newTop = rect.top + flake.speed;
let newLeft = rect.left + flake.xOffset;
if (newTop > window.innerHeight) {
newTop = -50;
newLeft = Math.random() * window.innerWidth;
}
flake.element.style.top = `${newTop}px`;
flake.element.style.left = `${newLeft}px`;
requestAnimationFrame(animate);
};
animate();
}
handleMouseMove(e) {
this.snowflakes.forEach((flake) => {
const rect = flake.element.getBoundingClientRect();
const flakeCenterX = rect.left + rect.width / 2;
const flakeCenterY = rect.top + rect.height / 2;
const dx = e.clientX - flakeCenterX;
const dy = e.clientY - flakeCenterY;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
const pushFactor = (100 - distance) / 5;
flake.element.style.transition = "transform 0.5s ease-out";
flake.element.style.transform = `translate(${dx * pushFactor * -0.01}px, ${
dy * pushFactor * -0.01
}px) scale(1.5)`;
flake.element.querySelector("svg").style.filter =
"drop-shadow(0 0 5px gold)";
} else {
flake.element.style.transition = "transform 0.5s ease-out";
flake.element.style.transform = "translate(0, 0) scale(1)";
flake.element.querySelector("svg").style.filter = "none";
}
});
}
createStars() {
const numStars = 50;
for (let i = 0; i < numStars; i++) {
const star = document.createElement("div");
star.classList.add("star");
star.style.left = `${Math.random() * 100}%`;
star.style.top = `${Math.random() * 50}%`;
star.style.animationDelay = `${Math.random() * 5}s`;
star.style.opacity = Math.random() * 0.5 + 0.5;
this.container.appendChild(star);
}
// Add stars
setInterval(() => {
const shootingStar = document.createElement("div");
shootingStar.classList.add("star");
shootingStar.style.left = `${Math.random() * 100}%`;
shootingStar.style.top = `${Math.random() * 50}%`;
shootingStar.style.width = "2px";
shootingStar.style.height = "2px";
shootingStar.style.background = "linear-gradient(45deg, white, transparent)";
shootingStar.style.opacity = "1";
shootingStar.style.transform = "translateX(-100vw) translateY(100vh)";
shootingStar.style.transition = "transform 1s linear";
this.container.appendChild(shootingStar);
setTimeout(() => {
shootingStar.style.transform = "translateX(0) translateY(0)";
}, 50);
setTimeout(() => {
shootingStar.remove();
}, 1050);
}, 5000);
}
}
// Initialize
window.addEventListener("load", () => {
new SnowfallAnimation();
});






