Home > front end >  Staggered, sequential animation with delay
Staggered, sequential animation with delay

Time:12-25

I have 5 blank boxes, and I would like each of them to be filled up in order every 1 second. How do I do this? My JS is wrong and not working.

let blankSquare = document.querySelectorAll(".square");

function fillUp() {
  setInterval(() => {
    blankSquare.classList.add(".fill")
  }, 1000)
}


blankSquare.addEventListener("fillUp");
.square {
  margin: 1vh;
  height: 3vh;
  width: 3vh;
  background-color: none;
  border: solid 2px grey;
}

.fill {
  background-color: grey;
}
<div >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</div>

CodePudding user response:

Staggered animation using CSS

Here's an example where you don't necessarily need JavaScript, but simply a style attribute containing a CSS var (variable) like style="--anim=N" where N is an index from 0 to N, and use CSS calc() for the animation-delay property:

.square {
  height: 3vh;
  aspect-ratio: 1;
  border: solid 2px grey;
  animation: fill 0.3s calc(var(--anim) * 1s) forwards;
}

@keyframes fill {
  to { background: grey; }
}
<div >
  <div  style="--anim:0"></div>
  <div  style="--anim:1"></div>
  <div  style="--anim:2"></div>
  <div  style="--anim:3"></div>
  <div  style="--anim:4"></div>
</div>

If you don't want to hardcode manually the style attribute, simply add this JS:

const ELS = (sel, el) => (el || document).querySelectorAll(sel);
ELS(".square").forEach((el, i) => el.style.setProperty("--anim", i));

Staggered animation using JavaScript

Given a function in JavaScript with which you can decide when to start your staggered animation:

Use setTimeout instead of setInterval inside a recursive fillUp function which accepts as arguments 1: a collection of elements, 2: a start index.
An incremented index is passed for every next recursive function call

const fillUp = (els, i = 0) => {
  els[i].classList.add("fill");
  i  = 1;
  if (i < els.length) setTimeout(() => fillUp(els, i), 1000);
};

fillUp(document.querySelectorAll(".square"));
.square {
  height: 3vh;
  aspect-ratio: 1;
  border: solid 2px grey;
}

.fill {
  background-color: grey;
}
<div >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</div>

Related articles / resources:

CodePudding user response:

You can store the index of the item in a variable, and increment it inside the interval.

let blankSquare = document.querySelectorAll(".square");

let index = 0;

function fillUp() {
  setInterval(() => {
    blankSquare[index  ].classList.add("fill")
  }, 1000)
}


fillUp()
.square {
  margin: 1vh;
  height: 3vh;
  width: 3vh;
  background-color: none;
  border: solid 2px grey;
}

.fill {
  background-color: grey;
}
<div >

  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>

</div>

  • Related