Implementing snow animation exclusively to a targeted div

I found some helpful code at and now I'm facing an issue where the snow effect is falling all over my page instead of just within the banner div...

// Storing Snowflake objects in an array
var snowflakes = [];

// Browser window size variables
var browserWidth;
var browserHeight;

// Number of visible snowflakes
var numberOfSnowflakes = 50;

// Flag for resetting snowflake positions
var resetPosition = false;

// Accessibility settings
var enableAnimations = false;
var reduceMotionQuery = matchMedia("(prefers-reduced-motion)");

// Handle animation accessibility preferences 
function setAccessibilityState() {
  if (reduceMotionQuery.matches) {
    enableAnimations = false;
  } else {
    enableAnimations = true;
  }
}
setAccessibilityState();

reduceMotionQuery.addListener(setAccessibilityState);

//
// Initialization function
//
function setup() {
  if (enableAnimations) {
    window.addEventListener("DOMContentLoaded", generateSnowflakes, false);
    window.addEventListener("resize", setResetFlag, false);
  }
}
setup();

//
// Snowflake object constructor
//
function Snowflake(element, speed, xPos, yPos) {
  // Set initial properties
  this.element = element;
  this.speed = speed;
  this.xPos = xPos;
  this.yPos = yPos;
  this.scale = 1;

  // Motion variables
  this.counter = 0;
  this.sign = Math.random() < 0.5 ? 1 : -1;

  // Initial opacity and size
  this.element.style.opacity = (.9 + Math.random()) / 3;
}

//
// Function to move the snowflake
//
Snowflake.prototype.update = function() {
  this.counter += this.speed / 5000;
  this.xPos += this.sign * this.speed * Math.cos(this.counter) / 40;
  this.yPos += Math.sin(this.counter) / 40 + this.speed / 30;
  this.scale = .5 + Math.abs(10 * Math.cos(this.counter) / 20);

  setTransform(Math.round(this.xPos), Math.round(this.yPos), this.scale, this.element);

  if (this.yPos > browserHeight) {
    this.yPos = -50;
  }
}

//
// Set snowflake position and size efficiently
//
function setTransform(xPos, yPos, scale, el) {
  el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0) scale(${scale}, ${scale})`;
}

//
// Generate snowflakes
//
function generateSnowflakes() {

  var originalSnowflake = document.querySelector(".snowflake");
  var snowflakeContainer = originalSnowflake.parentNode;
  snowflakeContainer.style.display = "block";

  browserWidth = document.documentElement.clientWidth;
  browserHeight = document.documentElement.clientHeight;

  for (var i = 0; i < numberOfSnowflakes; i++) {
    var snowflakeClone = originalSnowflake.cloneNode(true);
    snowflakeContainer.appendChild(snowflakeClone);

    var initialXPos = getPosition(50, browserWidth);
    var initialYPos = getPosition(50, browserHeight);
    var speed = 5 + Math.random() * 40;

    var snowflakeObject = new Snowflake(snowflakeClone,
      speed,
      initialXPos,
      initialYPos);
    snowflakes.push(snowflakeObject);
  }

  snowflakeContainer.removeChild(originalSnowflake);

  moveSnowflakes();
}


function moveSnowflakes() {

  if (enableAnimations) {
    for (var i = 0; i < snowflakes.length; i++) {
      var snowflake = snowflakes[i];
      snowflake.update();
    }
  }

  if (resetPosition) {
    browserWidth = document.documentElement.clientWidth;
    browserHeight = document.documentElement.clientHeight;

    for (var i = 0; i < snowflakes.length; i++) {
      var snowflake = snowflakes[i];

      snowflake.xPos = getPosition(50, browserWidth);
      snowflake.yPos = getPosition(50, browserHeight);
    }

    resetPosition = false;
  }

  requestAnimationFrame(moveSnowflakes);
}


function getPosition(offset, size) {
  return Math.round(-1 * offset + Math.random() * (size + 2 * offset));
}


function setResetFlag(e) {
  resetPosition = true;
}
#snowflakeContainer {
  position: absolute;
  left: 0px;
  top: 0px;
  display: none;
}

.snowflake {
  position: fixed;
  background-color: #ffffff;
  user-select: none;
  z-index: 1000;
  pointer-events: none;
  border-radius: 50%;
  width: 10px;
  height: 10px;
}
<div class="mainbanner">
  <div id="snowflakeContainer">
    <span class="snowflake"></span>
  </div>
  <br>
  <center>
    <p class="topText" style="font-size:8vw;"> Welcome to the ultimate <br>sleepover experience</p><br><br><br>
    <p class="topText" style="font-size:4vw;"> By Ultimate Teepee Party</p>

    <br><br><br>
    <a class="btn_1" href="book.html">Book Your Party</a></center>


</div>

Is there a way to make the snow effect only appear inside the specified banner div rather than covering the entire page?

Answer №1

After examining the snow demo page using inspect element, it becomes apparent that the author opted to embed an entire HTML page instead of utilizing a div element. The reasoning behind this choice lies in the fact that the JavaScript snippet

browserHeight = document.documentElement.clientHeight
relates to the browser's width. Thus, without modifying the JS code, the snow effect only functions properly on the entire page, as seen in the working demo linked below. If you desire the effect to be confined to a specific element, consider adjusting the script calculation based on the element's position. Alternatively, you can follow the author's approach and embed a document into the entire page.

JsFiddle

<style>
  #snowflakeContainer {
    position: fixed;
    left: 0px;
    top: 0px;
    display: none;
    width: 100vw;
    height: 100vh;
  }

  .snowflake {
    position: fixed;
    background-color: #CCC;
    user-select: none;
    z-index: 1000;
    pointer-events: none;
    border-radius: 50%;
    width: 10px;
    height: 10px;
    background: red;
  }

  <!-- more styles -->

</style>

<div id="snowflakeContainer">
  <span class="snowflake"></span>
  <div class="banner">
    <!-- content here -->
  </div>
</div>

<!-- JavaScript section -->

</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Design unique bar graphs to display on your website

I'm working on developing a webpage that will display dynamic data in a visually appealing bar graph. The design and aesthetics of the graph are crucial in this project. You can view the desired design of the bar graph by clicking on this link to the ...

The link containing special characters like % cannot access the api

I am facing an issue with retrieving a signUrl from S3. When I make the call with special characters like %, my code does not parse it correctly and I receive a 404 not found error. Here is the ajax request I am using: My API setup: app.get('/websi ...

How can you switch the property of an object within a VueJS array?

I'm currently working on developing a user feedback form that allows users to rate the quality of the food items they have ordered. I have an array called foodItems that displays the list of available food items along with predetermined reactions. My ...

Creating a seamless top border that remains unaffected by border radius

I'm currently working on mimicking the style of Google Calendar, and I've encountered an issue with the text input box. When clicked, it should look like this: https://ibb.co/6Hqrnt4 However, what I've created ends up looking like this: htt ...

Issue encountered when attempting to utilize multiple datasets with Twitter Typeahead/Bloodhound

Hello, I am currently learning how to use Typeahead and Bloodhound with the latest javascript. Below is a snippet of my code: Html: <div id="multiple-datasets"> <input class="typeahead" type="text" placeholder="NBA and NHL teams"> </div ...

Executing a task once all asynchronous AJAX calls are finished in jQuery

I have been attempting to achieve a specific goal by utilizing two separate Ajax calls. My aim is to trigger a third Ajax call only after the first two have completed entirely. However, despite my efforts to call the first two functions separately, it se ...

The JOI validation process is failing to return all error messages, even though the "abort early" option

I have been encountering an issue while trying to validate my payload using a joi schema. Instead of returning the errors specified in the schema, only one error is being displayed. Even when I provide a payload with name as "int", it only shows one custom ...

Items on the list will not be displayed side by side

I am facing an issue for which I cannot find a solution. While creating a Drupal site, I am trying to arrange these list items side by side. Each item has a width of 45%, so theoretically it should be possible to have 2 items next to each other. However, ...

Creating a fixed value in Expressjs middleware

Take a look at this snippet of code: var app = require('express')() app.get('/',function(req,res){ var flag = 0 console.log(flag) res.send('ok') flag++ } app.liste ...

``Can you provide steps on arranging two divs in a side by side layout

I need assistance with aligning two divs next to each other, both containing images. The goal is for the divs to remain side by side and for the images to automatically resize based on the screen size. When the screen size is reduced, I want the images t ...

What is the process for transforming the search bar into an icon located at the top of a WordPress site?

For the past few weeks, I've been attempting to convert the search bar on my website (which is currently a plugin) into an icon positioned near the header. I've experimented with modifying the child theme's functions.php, the parent theme&a ...

Are you looking for a demonstration of "Creative Loading Effects" that triggers when the page is loaded?

I came across this demo for a preloader on my website called Creative Loading Effects, specifically the "3D Bar Bottom" effect, which I find very exciting. However, I noticed that it only loads when we press the button, and not automatically when the page ...

Preserve the content in the text box corresponding to the selected radio button

In my form, there are multiple radio buttons, each with an associated text box value. Users can only select one radio button at a time and submit the form. However, sometimes users will enter data in a textbox for one radio button, then switch to another o ...

Triggers the request for Windows authentication when accessing a webpage on a website

Whenever I attempt to access a specific page on my website, a login screen pops up asking for my username and password. Even after entering the correct credentials and clicking OK or Cancel, the page still loads as normal. I can't figure out why this ...

Identifying Mistakes during Promise Initialization

Looking for a more efficient way to work with Bluebird promises Promise.resolve() .then(function() {return new MyObject(data)}) .then.....etc .catch(function (e){ //handle it}) I am dealing with MyObject and data coming from an external sourc ...

The effectiveness of recursion in asynchronous function calls within AngularJS

My task involves creating a JSON output in tree structure from recursive async calls. The code I have developed for this purpose is detailed below: $scope.processTree = function (mData, callback) { _processTree.getWebCollection( ...

What alternative can be used for jquery isotope when JavaScript is not enabled?

Is there a backup plan for jQuery isotope if JavaScript isn't working? For instance, if I'm using the fitColumns feature, is there an alternative layout style available in case JavaScript is disabled, similar to what is seen on the new Myspace? ...

Tips for forming JSON object within an array with the help of jQuery

Is there a way to generate JSON Objects using jQuery? I currently have a JSON Object in the following structure: { "1":{ "c_roleid":null, "ObjectID":1, "c_appname":"Default", "c_display":true, "c_add":null, ...

Tips for aligning input elements in the center using HTML and CSS

https://i.sstatic.net/3B7F9.jpg Can someone help me center the input vertically within the image? I'm not sure how to achieve this. .headmenu { background-color: rgb(47, 47, 47); width: auto; height: 30px; } .headmenu-right { float: right ...

<v-time-picker> - issue with time selection

<v-time-picker> - Are you certain that the component was properly registered? If dealing with recursive components, remember to include the "name" option <div class="form-inline"> <label for="">Time</label> <v-time-pick ...