JavaScript Snow

JavaScript Snow

Add a JavaScript snow animation to your site like it's 1998!

Here's how you can add a snow animation with JavaScript to your site just for the festive season :)

See a demo by watching the tutorial here and for my thoughts on why it's a bad idea!

1. Setup Constants

Let's setup some variables to hold some info on the appearance of our snow animation.

const NUMBER_OF_SNOWFLAKES = 300;
const MAX_SNOWFLAKE_SIZE = 5;
const MAX_SNOWFLAKE_SPEED = 2;
const SNOWFLAKE_COLOUR = '#ddd';

const snowflakes = [];

We'll also create an empty array called snowflakes which is going to keep track of all the individual snowflakes on the page.

2. Create a canvas

All our snowflakes are going to be drawn onto a canvas element so let's create that and drop it onto the current document.

const canvas = document.createElement('canvas');
canvas.style.position = 'absolute';
canvas.style.pointerEvents = 'none';
canvas.style.top = '0px';
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);

const ctx = canvas.getContext('2d');

We're sizing the canvas to fit the entire window and setting the pointer-event CSS property to none so it makes the canvas invisible and the user can still click things behind it.

Finally, we'll get the 2d canvas context, which we can use to draw our snowflakes on.

But first, we need a function to generate a snowflake.

3. Create a snowflake

const createSnowflake = () => ({
    x: Math.random() * canvas.width,
    y: Math.random() * canvas.height,
    radius: Math.floor(Math.random() * MAX_SNOWFLAKE_SIZE) + 1,
    color: SNOWFLAKE_COLOUR,
    speed: Math.random() * MAX_SNOWFLAKE_SPEED + 1,
    sway: Math.random() - 0.5
});

This function will create and return a snowflake object which is at some random position on the page. We'll also create a random size (radius) for it, set its colour to the constant we defined and also give it a random speed with a minimum value.

In the second part of the tutorial, we introduce a sway property in order to move the snowflake either left or right as it falls down the page.

Now we need a way to draw the snowflake onto the canvas.

4. Draw a snowflake

const drawSnowflake = snowflake => {
    ctx.beginPath();
    ctx.arc(snowflake.x, snowflake.y, snowflake.radius, 0, Math.PI * 2);
    ctx.fillStyle = snowflake.color;
    ctx.fill();
    ctx.closePath();
};

We're just going to draw a circle with a radius as specified by the property on the snowflake object that's passed in.

5. Update a snowflake

const updateSnowflake = snowflake => {
    snowflake.y += snowflake.speed;
    snowflake.x += snowflake.sway;
    if (snowflake.y > canvas.height) {
        Object.assign(snowflake, createSnowflake());
    }
};

Here, we'll take one of our snowflake objects and update its x and y positions on the page. If it gets to the bottom of the page, we'll re-assign the reference of the snowflake to a new snowflake object.

6. Animating snowflakes

const animate = () => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    snowflakes.forEach(snowflake => {
        updateSnowflake(snowflake);
        drawSnowflake(snowflake);
    });

    requestAnimationFrame(animate);
};

The animate function clears the current canvas and then loops through our array of snowflakes and updates their position, then draws them onto the canvas.

We can make a really smooth animation by simply calling this function repeatedly by passing it to requestAnimationFrame.

Of course, we haven't put any snowflake objects into our snowflakes array yet so let's populate those now and kick off the animation by calling the animate function.

for (let i = 0; i < NUMBER_OF_SNOWFLAKES; i++) {
    snowflakes.push(createSnowflake());
}

animate();

We should have a fully working snowfall animation on our page now!

7. Adding Event Listeners

If you try and resize your browser window at this point or scroll down to more content (if it exists on your page) then you'll notice that the snowfall effect is fixed to the top of the page and doesn't resize to fit the browser window.

Let's finish off our beautiful snowfall animation with a couple of event listeners to handle this.

window.addEventListener('resize', () => {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
});

window.addEventListener('scroll', () => {
    canvas.style.top = `${window.scrollY}px`;
});

Because we've written everything in JavaScript with no extra HTML/CSS required, we can just copy the code and drop it into any site. For example, here's how it looks on Amazon's site:

JavaScript snow on Amazon

Conclusion

As mentioned in the video, this is just a bit of fun and not something you should probably add to your site unless your company is insistent on sending your site back to the 1990s :)

Thanks for reading and be sure to check out the full tutorial here if you want more details: