Search code examples
javascripthtmlcssdombackground-image

Loop not overriding style of a div


function lineComplete() {
  let line = document.getElementById("line");
  for (let percentage = 0; percentage <= 100; percentage++) {
    setTimeout(function() {
      line.style.width = `${percentage}%`;
    }, percentage * 25);
    if (percentage === 100) {
      undo();
    }
  }

  function undo() {
    for (let percent = 100; percent >= 0; percent--) {
      setTimeout(function() {
        line.style.width = `${percent}%`;
      }, percent * 25);
    }
  }
}
#outLine {
  width: 60%;
  height: 20px;
  margin: 10px 0px;
  background-image: linear-gradient(to right, #f12711, #f12711);
  border-radius: 20px;
}

#line {
  background-image: linear-gradient(to right, #f12711, #f5af19);
  height: 100%;
  width: 100%;
  border-radius: 20px;
}
<body onload="lineComplete()">
  <div id="outLine">
    <div id="line"></div>
  </div>
</body>

In the above snippet, I am trying to show a loader-like effect which I am able to achieve. The problem is that when the width of line is 100%, I am trying to fire the function undo. This also works fine. There is a loop in undo which decreases the width of line and gradually bring its width to 0%. The loop also works fine as I have tried to run it after replacing its contents with alert() and it worked fine. But with the present situation, the loop is not resizing the line. I think that it is not able to override the styles.


Solution

  • function lineComplete() {
      let line = document.getElementById("line");
      for (let percentage = 0; percentage <= 100; percentage++) {
        setTimeout(function() {
          line.style.width = `${percentage}%`;
          if (line.style.width === "100%") {
              undo();
          }
        }, percentage * 25);
      }
    
      function undo() {
        for (let percent = 100; percent >= 0; percent--) {
          setTimeout(function() {
            line.style.width = `${100 - percent}%`;
          }, percent * 25);
        }
      }
    }
    #outLine {
      width: 60%;
      height: 20px;
      margin: 10px 0px;
      background-image: linear-gradient(to right, #f12711, #f12711);
      border-radius: 20px;
    }
    
    #line {
      background-image: linear-gradient(to right, #f12711, #f5af19);
      height: 100%;
      width: 100%;
      border-radius: 20px;
    }
    <body onload="lineComplete()">
      <div id="outLine">
        <div id="line"></div>
      </div>
    </body>

    The problem was that when you decrease, the later iterations are scheduled to run earlier than the earlier iterations. Let's negate percentage (100 - percentage) and it will work.