Search code examples
javascripthtmlcssopacity

Gradually changing opacity with JavaScript doesn't work


I have this element:

<div id="newDimention">
  <div class="newDimention">
  </div>
</div>  

I'm trying to change its opacity with javascript:

let newDimention=document.getElementById('newDimention');
setTimeout(()=>{
 setDimention();
  newDimention.innerText="You've uncovered the third dimension."
   newDimention.style.color="purple";
    newDimention.style.fontSize='30px';
    newDimention.style.marginTop='30px';
    newDimention.style.opacity="0";
    })



const setDimention = () => {
for (var i = 0,b=14; i <= 500; i++) {
 setTimeout(()=>{
//document.getElementById("newDimention").style.opacity=String(Math.round(i/50)/10);
   newDimention.style.opacity=String(Math.round(i/50)/10);
 },i*b)
}
}

I tried without converting to a string, tried accessing by the class, id. Devtools clearly show that String(Math.round(i/50)/10) gradually increases each time as it should be. But newDimention.style.opacity remains '0' each time.

Then once String(Math.round(i/50)/10)==='1', newDimention.style.opacity changes to '1' instantly. So it remains '0' for some reason until i===500, then suddenly changes to '1'. I don't have any other functions manipulating this element. And if I remove the line newDimention.style.opacity=String(Math.round(i/50)/10); the opacity stays at '0', so this line is supposed to change the opacity of this element.

Why is this happening?


Solution

  • While writing this question I realized that I used var instead of let in the for loop, so when the functions got fired eventually after setTimeout, they used i===500, the latest value. Changing it to let fixed it:

    const setDimention = () => {
    for (let i = 0,b=14; i <= 500; i++) {
     setTimeout(()=>{
    //document.getElementById("newDimention").style.opacity=String(Math.round(i/50)/10);
       newDimention.style.opacity=String(Math.round(i/50)/10);
     },i*b)
    }
    }
    

    From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let:

    "let allows you to declare variables that are limited to a scope of a block statement, or expression on which it is used, unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope".