This single-file snowfall effect uses HTML Canvas and JavaScript to create a smooth, lightweight animation of falling snowflakes across the screen. The canvas automatically resizes to fit the browser window, while each snowflake is randomly generated with its own size, speed, and horizontal drift to simulate natural movement. The animation runs efficiently using requestAnimationFrame, continuously clearing and redrawing the scene to give the illusion of gentle snowfall. Because all HTML, CSS, and JavaScript are contained in one file, it is easy to use, customize, and deploy without any external dependencies.
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Set character encoding -->
<meta charset="UTF-8" />
<!-- Page title -->
<title>Snowfall Effect</title>
<style>
/* Remove default spacing and make page full height */
html, body {
margin: 0; /* Remove default margin */
padding: 0; /* Remove default padding */
background: #0b1d3a; /* Dark blue background (night sky) */
overflow: hidden; /* Prevent scrollbars */
height: 100%; /* Full viewport height */
}
/* Make canvas fill the screen */
canvas {
display: block; /* Remove inline spacing */
}
</style>
</head>
<body>
<!-- Canvas where snow will be drawn -->
<canvas id="snow"></canvas>
<script>
// Get the canvas element by its ID
const canvas = document.getElementById("snow");
// Get 2D drawing context from canvas
const ctx = canvas.getContext("2d");
// Function to resize canvas to window size
function resize() {
canvas.width = window.innerWidth; // Match window width
canvas.height = window.innerHeight; // Match window height
}
// Initial resize when page loads
resize();
// Resize canvas whenever window size changes
window.addEventListener("resize", resize);
// Array to store all snowflake objects
const snowflakes = [];
// Total number of snowflakes
const SNOW_COUNT = 200;
// Create snowflake objects
for (let i = 0; i < SNOW_COUNT; i++) {
snowflakes.push({
x: Math.random() * canvas.width, // Random horizontal position
y: Math.random() * canvas.height, // Random vertical position
r: Math.random() * 3 + 1, // Radius (size) of snowflake
speed: Math.random() * 2 + 0.5, // Falling speed
drift: Math.random() * 0.6 - 0.3 // Horizontal movement (wind)
});
}
// Main drawing function
function draw() {
// Clear entire canvas before redrawing
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Set snowflake color
ctx.fillStyle = "white";
// Start a new drawing path
ctx.beginPath();
// Draw each snowflake
for (const s of snowflakes) {
ctx.moveTo(s.x, s.y); // Move drawing cursor
ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2); // Draw circular snowflake
}
// Fill all snowflakes with color
ctx.fill();
// Update snowflake positions
update();
// Request next animation frame (smooth animation)
requestAnimationFrame(draw);
}
// Update snowflake movement
function update() {
for (const s of snowflakes) {
s.y += s.speed; // Move snowflake downward
s.x += s.drift; // Move snowflake sideways (wind)
// If snowflake falls below screen, reset to top
if (s.y > canvas.height) {
s.y = -s.r; // Start above canvas
s.x = Math.random() * canvas.width; // Random horizontal position
}
// Wrap snowflake horizontally
if (s.x > canvas.width) s.x = 0;
if (s.x < 0) s.x = canvas.width;
}
}
// Start the animation loop
draw();
</script>
</body>
</html>