For Loop Black Magic -- grow/shrink height

I am trying to do something that I thought was very simple, shrink the height of the welcome page to 0 on some event.

At first I wanted to grow the welcome page, ended up using this code:

for (let i = 0; i < 100; i++) {
  setTimeout(
    function() {
      let test =$('#bg0');
      test = test.css("height", i + "%");
    }, 10 * i
  );
}

I actually needed to ask here, on the forums for help on the last bit of code for that…

It worked, and I thought I understood it.

I now changed my mind and want to shrink the welcome page rather than grow it.

So I modified it to this:

for (let i = 100; i > 0; i--) {
  setTimeout(
    function() {
      let test =$('#bg0');
      test = test.css("height", i + "%");
    }, 10 * i
  );
}

Much to my dismay it did the exact same thing that the previous code did- grow the welcome page.

So I broke down the block of code by putting console.logs everywhere and it turns out that the settimeout isn’t running until the loop condition breaks … i.e. i>0

this is aggravating because from what I have read and been taught the for loop initializes, checks the condition, runs the code within its bracket then increments/decrements the variable.

So why is the vudoo happening and what is the reasoning/explanation?

For my modified code the for loop starts decrementing from 100 but for some reason when the loop condition breaks, the variable i is set to 0 and not 100 in my function, which is why my modified code won’t shrink the welcome page.

Sorry for the book, and I would immensely appreciate assistance on this!

for (let i = 100; i > 0; i--) {
  console.log('pre timeout')
  console.log(i)
  setTimeout(
    function() {
      console.log('in function');
      console.log(i);
      let test =$('#bg0');
      test = test.css("height", i + "%");
    }, 10 * i
  );
  console.log('post timeout')
  console.log(i)
}

I suspect the issue is due to the delay of the setTimeout:

  setTimeout(fn(){} , 10 * i)

in the ascending version i start from 0 so it’s called immediately.
in the descending version, i start at 100 so the function is deferred to 1000 ms later -->
the first function is the last to be executed.


That said, is there a reason to do this with a loop and a setTimeout?
You are creating a 100 deferred function.

Why not a css transition or animation?

Thanks for the reply.

I have seen a lot of people’s websites do this and I am not sure how they do it, any method would work for me.

I have tried using different timeout durations but it does not seem to correlate to my problem as far as I can tell.

I did not know that growing and shrinking the height of an element was something that could be easily done in CSS.

I made the assumption that manipulating an element in the DOM was a job for js since that is what it was created for as far as I know, it’s just really weird how difficult it seems to do what seems so simple.

I have looked on the internet and tried a lot of different ways to go about it

But feel free to show me what you mean, I just made a pen for this question.

Thanks again

This is a very basic animation that scales en element from top vertically:

@keyframes scale {
  0% {
    transform: scaleY(0);
    transform-origin: 100% 0%;
  }
  100% {
    transform: scaleY(1);
    transform-origin: 100% 0%;
  }
}

Simply add that CSS animation with your desired property to your element.

For example:

#bg1{
animation: scale 1s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
}

You can find lots of resources about css animations online as well :slight_smile:
Some people way more talented than me, can make some absurd and awesome animations

Hope this helps

1 Like

You need an animation for this using the transition CSS property:

https://www.w3schools.com/css/css3_transitions.asp

The transition API gives you 4 main properties you can change even at runtime:

  • transition
  • transition-delay
  • transition-duration
  • transition-property
  • transition-timing-function

Or you can also use all these properties in a shorthand.

Duration would be how much you want it to last (seconds or msec). For example to animate growth and shrinkage both in one go:

element {
  width: ??px;
  height: ??px;
  transition: height 5s;
  -webkit-transition: height 5s;
}

This way, anytime the height property of said element changes (either via JS or CSS itself) it will animate in both directions (shrink/grow).

1 Like

Hey man I am sorry for the delay in thanks.

I was locked out of FCC because of their backend user authentication bug.

But seriously, I was writing animations the long and difficult route and did not see or understand the value nor simplicity of CSS animations until your reply; which completely changed the way I write code now, so thanks a million.

Thanks a lot! I have no idea how I made it this far without knowing what CSS animations are. Ever since @Marmiz initially elucidated this topic for me, I am now turning to CSS first for animations; since it’s just 3000x simpler.

Albeit thanks a lot; your reply was concise and helpful