0

I have one outer box and an inner box and there are some identical boxes with the same class names inside the second box. I want all of these boxes to appear one after the other with this fade-in effect. So far I have done it for the outer and inner div, and I wanted to use the same function for all the identical boxes inside. I tried to do the same for outer and inner div since they too just need the exact same function. But I wasn't successful. Here is my code :

html:

<div class="div1">
    <div class="div2">
        <div class="div3"></div>
        <div class="div3"></div>
        <div class="div3"></div>
        <div class="div3"></div>
        <div class="div3"></div>
    </div>
</div>

javascript:

let div1 = document.getElementsByClassName("div1")[0];
let div2 = document.getElementsByClassName("div2")[0];
let div3 = document.getElementsByClassName("div3");

div1.style.visibility = "hidden";
div2.style.visibility = "hidden";

function first() {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            div1.style.animation = "fadein 5s";
            div1.style.visibility = "visible";
            resolve("div1 worked!");
        }, 1000);
    });
}
function second() {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            div2.style.animation = "fadein 5s";
            div2.style.visibility = "visible";
            resolve("div2 worked!");
        }, 1000);
    });
}

function abc(element) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            element.style.animation = "fadein 5s";
            element.style.visibility = "visible";
            resolve("third");
        }, 1000);
    });
}

first()
    .then(second)
    .then((div3) => {
        div3.forEach((element) => {
            abc(element);
        });
    });

css

.div1 {
    width: 400px;
    height: 500px;
    background-color: yellow;
}
.div2 {
    width: 350px;
    height: 400px;
    background-color: green;
}
.div3 {
    width: 300px;
    height: 50px;
    background-color: grey;
    margin: 10px;
}
@keyframes fadein {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

The first two works and I don't know how I can reuse the function for the remaining div3 class divs. I tried to reuse the function for the first two as well, but it didn't work and ended up writing same functions again and again. I want to call function abc for each element in div3 and only execute the next one after the first element is done - like how it executes for first and second but using the same function. Not sure how to do that and I'm stuck. Here is a codepen link. As of now all the div3 divs appear together with the second div.

Akhila
  • 489
  • 6
  • 18
  • https://stackoverflow.com/questions/33790474/jquery-fadein-children-elements-of-different-element-types-sequentially – Thrallix Dec 04 '20 at 16:00
  • 2
    animation-delay may help you - you use the same animation name on all the elements but delay them starting their animations by different amounts. – A Haworth Dec 04 '20 at 16:02

2 Answers2

1

You can use loops and animation-delay to apply the animation as per your need. The following code will work for this case. Code is full with comments to explain what is happening at each point. I have also slightly modified the css so that we don't get any weird blinking effect while executing the code.

//Declare all the classes - 
let divs = ["div1", "div2", "div3"];

//Initiate a delay for each iteration
let delay = 0;

//Run a loop for each class
for(let i = 0; i<divs.length; i++){
  
  //Get the element
  let div = document.getElementsByClassName(divs[i]);
  
  //Run a loop for element with the class
  //(We only have one div with the classes div1 and div2. So it will run one time for them.
  //We have 5 divs with div3 class. It will run 5 times in that case 
  for(let j = 0; j<div.length; j++){
    
    //Get the individual element and add animation with delay
    //The delay will also ensure that the animation starts only when the previous element has finished the animation
    div[j].style.animation = `fadein 5s ${delay}s forwards` ;
    div[j].classList.add("show");
    
    //Increase delay with every iteration
    delay+=5;
  }
}
div {
  visibility: hidden;
}

.div1 {
  width: 400px;
  height: 500px;
  background-color: yellow;
}
.div2 {
  width: 350px;
  height: 400px;
  background-color: green;
}
.div3 {
  width: 300px;
  height: 50px;
  background-color: grey;
  margin: 10px;
}

.show {
  opacity: 0;
  visibility: visible;
}

@keyframes fadein {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
<div class="div1">
  <div class="div2">
    <div class="div3">1</div>
    <div class="div3">2</div>
    <div class="div3">3</div>
    <div class="div3">4</div>
    <div class="div3">5</div>
  </div>
</div>

The script may seem very long but it is only 10 lines long without the comments. This will also work if you increase or decrease the number of divs

Praneet Dixit
  • 1,393
  • 9
  • 25
-1

This is one way to solve the problem using setInterval for executing a piece of code every x seconds.

The function fadeIn takes an array of elements that will be faded in by adding the class "show" (se details for "show" in CSS-code below). This will animate the given elements.

The function start collects the elements that will be faded and fades in the first collection of element, then countinuesly fades in the rest of the elements in the array "elements" every 3 seconds.

function fadeIn(el) {
  // For every element in the collection
  for (var i = 0; i < el.length; i++) {
    // Add the class "show"
    el[i].classList.add('show');
  }
}

function start() {
  /*
    Collects all the elements that we want to fadeIn in order. First collection of elements will be animated firstly, second collection of elements will be animated secondly, etc.
  */
  var elements = [];
  elements.push(document.getElementsByClassName("div1"));
  elements.push(document.getElementsByClassName("div2"));
  elements.push(document.getElementsByClassName("div3"));
  
  // Show the first collection of elements
  fadeIn(elements[0]);
  
  // Show the rest of the element collections in array "elements"
  var i = 1;
  fadeInInterval = setInterval(function() {
    fadeIn(elements[i]);
    // If there is no more collections to fade in, end the setInterval
    if (i == elements.length-1) {
      clearInterval(fadeInInterval)
    }
    i++
  }, 3000) // Every 3 seconds
}

start();
div {
  visibility: hidden;
}

.div1 {
  width: 400px;
  height: 500px;
  background-color: yellow;
}
.div2 {
  width: 350px;
  height: 400px;
  background-color: green;
}
.div3 {
  width: 300px;
  height: 50px;
  background-color: grey;
  margin: 10px;
}

.show {
  animation: fadein 5s;
  visibility: visible;
}

@keyframes fadein {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
<div class="div1">
  <div class="div2">
    <div class="div3"></div>
    <div class="div3"></div>
    <div class="div3"></div>
    <div class="div3"></div>
    <div class="div3"></div>
  </div>
</div>
Tibbelit
  • 1,215
  • 10
  • 17