Shivam Katare

SnowFall effect using CSS and JavaScript Animations

5 min read

Cover Image for SnowFall effect using CSS and JavaScript Animations

Hello there! I am Shivam,

Today I'm going to show you how to create a beautiful falling snow effect for any webpage. Wouldn't that look amazing on your blog or portfolio site during the winter holidays?

To create this effect, we will use:

• HTML - to add a container for our snowflakes
• CSS - to style and position the snowflakes
• JavaScript - to programmatically generate and GSAP to animate the snowflakes

Sound good? Open up your code editor, and let's get started! We'll be working with 3 files:

  • index.html: Our HTML file with the container div

  • style.css: The CSS styles for our background and snowflakes

  • script.js: The JavaScript to generate and animate the snowflakes

Go ahead and create these 3 files now so you're ready to follow along!

Setting the Scene for Snow

To create individual snowflakes that can fall, we first need to set the stage. We'll start by adding a basic HTML structure with a container div where our snowflakes will live.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>Snow Fall</title>
</head>
<body>
  <div id="container"></div>

<!-- Below, we are importing GSAP library for animation and attaching our JavaScript file -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js" integrity="sha512-16esztaSRplJROstbIIdwX3N97V1+pZvV33ABoG1H2OyTttBxEGkTsoIVsiP1iaTtM8b3+hu2kB6pQ4Clr5yug==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="script.js"></script>
</body>
</html>

Painting a Wintry Background

Now we'll paint a wintry background for our snow to fall on. We'll use CSS to position the container div absolutely and add a winter background image.

Let's break down each part step-by-step:

The body styles

We first apply some base styles to the <body> element to set up our scene:

body {
  background-image: url(winter-landscape.jpg);  
  background-size: cover;
  background-position: center center;
  overflow: hidden;
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100vh;
  position: relative;
}
  • We set a winter landscape photo as the background-image.

  • Using background-size: cover , the image fills the entire background area.

  • We center the image vertically and horizontally with background-position: center center.

  • We hide any content overflow with overflow: hidden.

  • We remove default margins and paddings with margin: 0 and padding: 0.

  • Finally, we also added a width, height and a position: relative.

The container

We added a container to hold our snowflakes:

#container {
  position: absolute;
  top: 0;
  left: -10%;
  right: 0;
  width: 110vw;  
  height: 110vh;
  z-index: 1;
}
  • We position the container position: absolute within the <body>.

  • We position the top left corner using top: 0 and left: -10%.

  • Making the container width: 110vw and height: 110vh allows snowflakes to "fall offscreen".

  • We place the container above the background with z-index: 1.

The snowflakes

We style each snowflake as a circle:

#container .droplet {
  position: absolute;
  top: -20%;
  background: #fff;
  border-radius: 50%;
}
  • We position each snowflake position: absolute within the container.

  • We start each snowflake above the top with top: -20%.

  • We use background: #fff for a white color.

  • We make the circle shape using border-radius: 50%.

Crafting the Falling Snowflakes

Now for the fun part - we'll craft our snowflakes! We'll create a JavaScript function to generate snowflake elements with random styles like size, opacity, and speed.

Defining functions

We first define two functions:

randomInRange() - Generates a random number within a range.

createDroplet() - Creates and styles a single snowflake div.

const randomInRange = (max, min) => Math.floor(Math.random() * (max - min)) + min;
  • createDroplet Function:
const createDroplet = () => {
  const droplet = document.createElement("div");
  droplet.className = "droplet";

This function creates a new <div> element, assigns the class name "droplet" to it, and prepares to create the snowflake element.

const pos = randomInRange(100.5, 0);
droplet.style.left = `${pos}%`;

A random horizontal position (pos) is generated using the randomInRange function. The snowflake's left position is set using this value, creating a horizontal shift within the container.

const height = randomInRange(12, 4);
droplet.style.height = droplet.style.width = `${height}px`;

Similarly, a random height (height) for the snowflake is generated. The height and width of the snowflake element are set to this value, creating a circular shape.

const opacity = randomInRange(1, 0.8);
TweenMax.set(droplet, { opacity });

A random opacity value (opacity) is generated. The TweenMax.set function from the GSAP library is used to set the opacity of the snowflake element to this value, controlling its transparency.

const delay = randomInRange(10, 0);
const speed = randomInRange(17, 12);
const blurVal = randomInRange(4, 1);
const path = () => [
    { x: randomInRange(150, -150), y: randomInRange(150, -150) },
    { x: randomInRange(150, -150), y: randomInRange(150, -150) },
    { x: randomInRange(150, -150), y: randomInRange(150, -150) },
    { x: randomInRange(150, -150), y: randomInRange(150, -150) }
  ];

Several parameters for animating the snowflake are set: delay, speed, and blurVal. Additionally, a function path is defined, which returns an array of points. Each point contains random x and y coordinates to create a bezier path for the snowflake's animation.

TweenMax.to(droplet, speed, {
  y: 1520,
  delay,
  top: -300,
  filter: `blur(${blurVal}px)`,
  repeat: -1,
  bezier: {
    type: "soft",
    values: path(),
    autoRotate: true
  },
  ease: Power1.easeInOut
});

The TweenMax.to function animates the snowflake. It animates the snowflake's vertical (y) position from the top to 1520 (making it fall), along the bezier path defined by the path function. Additional properties such as delay, top, filter (to add a blur effect), repeat (to repeat the animation indefinitely), and ease (animation easing) are configured.

return droplet;
};

Finally, the createDroplet function returns the configured snowflake element.

  • Creating Snowflakes:

const dropletContainer = document.getElementById("container");

for (let i = 0; i < 200; i++) {
  const droplet = createDroplet();
  dropletContainer.appendChild(droplet);
}

This part of the code selects the container element from the HTML and uses a loop to create 200 snowflakes. For each iteration, the createDroplet function is called to generate a snowflake element, which is then appended to the container.

Wrapping Up

In creating this beautiful snowfall animation, we've seen how HTML provides the structure, CSS brings the style, and JavaScript injects the interactivity and motion.

Thanks for reading it. I hope it was insightful. All the source code used in this article is in my GitHub repository.

If you liked the article, please post likes 👍, give it a ⭐ and share it in your circles.

Let's connect. I share content related to web development, technical writing, and Open Source on these platforms.

Thanks for reading :)